Merge branch 'main' into java-kotlin-sensitive-logging-substring-barriers

This commit is contained in:
Owen Mansel-Chan
2025-11-25 23:24:58 +00:00
committed by GitHub
113 changed files with 16095 additions and 2994 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Add databaseMetadata and overlayChangedFiles relations
compatibility: full
databaseMetadata.rel: delete
overlayChangedFiles.rel: delete

View File

@@ -21,3 +21,4 @@ dataExtensions:
- ext/deallocation/*.model.yml
- ext/allocation/*.model.yml
warnOnImplicitThis: true
compileForOverlayEval: true

View File

@@ -2078,38 +2078,151 @@ predicate localExprFlow(Expr e1, Expr e2) {
localExprFlowPlus(e1, e2)
}
/**
* A canonical representation of a field.
*
* For performance reasons we want a unique `Content` that represents
* a given field across any template instantiation of a class.
*
* This is possible in _almost_ all cases, but there are cases where it is
* not possible to map between a field in the uninstantiated template to a
* field in the instantiated template. This happens in the case of local class
* definitions (because the local class is not the template that constructs
* the instantiation - it is the enclosing function). So this abstract class
* has two implementations: a non-local case (where we can represent a
* canonical field as the field declaration from an uninstantiated class
* template or a non-templated class), and a local case (where we simply use
* the field from the instantiated class).
*/
abstract private class CanonicalField extends Field {
/** Gets a field represented by this canonical field. */
abstract Field getAField();
/**
* Gets a class that declares a field represented by this canonical field.
*/
abstract Class getADeclaringType();
/**
* Gets a type that this canonical field may have. Note that this may
* not be a unique type. For example, consider this case:
* ```
* template<typename T>
* struct S { T x; };
*
* S<int> s1;
* S<char> s2;
* ```
* In this case the canonical field corresponding to `S::x` has two types:
* `int` and `char`.
*/
Type getAType() { result = this.getAField().getType() }
Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() }
}
private class NonLocalCanonicalField extends CanonicalField {
Class declaringType;
NonLocalCanonicalField() {
declaringType = this.getDeclaringType() and
not declaringType.isFromTemplateInstantiation(_) and
not declaringType.isLocal() // handled in LocalCanonicalField
}
override Field getAField() {
exists(Class c | result.getDeclaringType() = c |
// Either the declaring class of the field is a template instantiation
// that has been constructed from this canonical declaration
c.isConstructedFrom(declaringType) and
pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName())
or
// or this canonical declaration is not a template.
not c.isConstructedFrom(_) and
result = this
)
}
override Class getADeclaringType() {
result = this.getDeclaringType()
or
result.isConstructedFrom(this.getDeclaringType())
}
}
private class LocalCanonicalField extends CanonicalField {
Class declaringType;
LocalCanonicalField() {
declaringType = this.getDeclaringType() and
declaringType.isLocal()
}
override Field getAField() { result = this }
override Class getADeclaringType() { result = declaringType }
}
/**
* A canonical representation of a `Union`. See `CanonicalField` for the explanation for
* why we need a canonical representation.
*/
abstract private class CanonicalUnion extends Union {
/** Gets a union represented by this canonical union. */
abstract Union getAUnion();
/** Gets a canonical field of this canonical union. */
CanonicalField getACanonicalField() { result.getDeclaringType() = this }
}
private class NonLocalCanonicalUnion extends CanonicalUnion {
NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() }
override Union getAUnion() {
result = this
or
result.isConstructedFrom(this)
}
}
private class LocalCanonicalUnion extends CanonicalUnion {
LocalCanonicalUnion() { this.isLocal() }
override Union getAUnion() { result = this }
}
bindingset[f]
pragma[inline_late]
private int getFieldSize(Field f) { result = f.getType().getSize() }
private int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) }
/**
* Gets a field in the union `u` whose size
* is `bytes` number of bytes.
*/
private Field getAFieldWithSize(Union u, int bytes) {
result = u.getAField() and
private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) {
result = u.getACanonicalField() and
bytes = getFieldSize(result)
}
cached
private newtype TContent =
TNonUnionContent(Field f, int indirectionIndex) {
TNonUnionContent(CanonicalField f, int indirectionIndex) {
// the indirection index for field content starts at 1 (because `TNonUnionContent` is thought of as
// the address of the field, `FieldAddress` in the IR).
indirectionIndex = [1 .. SsaImpl::getMaxIndirectionsForType(f.getUnspecifiedType())] and
indirectionIndex = [1 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and
// Reads and writes of union fields are tracked using `UnionContent`.
not f.getDeclaringType() instanceof Union
} or
TUnionContent(Union u, int bytes, int indirectionIndex) {
exists(Field f |
f = u.getAField() and
TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) {
exists(CanonicalField f |
f = u.getACanonicalField() and
bytes = getFieldSize(f) and
// We key `UnionContent` by the union instead of its fields since a write to one
// field can be read by any read of the union's fields. Again, the indirection index
// is 1-based (because 0 is considered the address).
indirectionIndex =
[1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes)
.getUnspecifiedType())
.getAnUnspecifiedType())
)]
)
} or
@@ -2175,8 +2288,12 @@ class FieldContent extends Content, TFieldContent {
/**
* Gets the field associated with this `Content`, if a unique one exists.
*
* For fields from template instantiations this predicate may still return
* more than one field, but all the fields will be constructed from the same
* template.
*/
final Field getField() { result = unique( | | this.getAField()) }
Field getField() { none() } // overridden in subclasses
override int getIndirectionIndex() { none() } // overridden in subclasses
@@ -2187,32 +2304,33 @@ class FieldContent extends Content, TFieldContent {
/** A reference through a non-union instance field. */
class NonUnionFieldContent extends FieldContent, TNonUnionContent {
private Field f;
private CanonicalField f;
private int indirectionIndex;
NonUnionFieldContent() { this = TNonUnionContent(f, indirectionIndex) }
override string toString() { result = contentStars(this) + f.toString() }
override Field getAField() { result = f }
final override Field getField() { result = f.getAField() }
override Field getAField() { result = this.getField() }
/** Gets the indirection index of this `FieldContent`. */
override int getIndirectionIndex() { result = indirectionIndex }
override predicate impliesClearOf(Content c) {
exists(FieldContent fc |
fc = c and
fc.getField() = f and
exists(int i |
c = TNonUnionContent(f, i) and
// If `this` is `f` then `c` is cleared if it's of the
// form `*f`, `**f`, etc.
fc.getIndirectionIndex() >= indirectionIndex
i >= indirectionIndex
)
}
}
/** A reference through an instance field of a union. */
class UnionContent extends FieldContent, TUnionContent {
private Union u;
private CanonicalUnion u;
private int indirectionIndex;
private int bytes;
@@ -2220,24 +2338,31 @@ class UnionContent extends FieldContent, TUnionContent {
override string toString() { result = contentStars(this) + u.toString() }
final override Field getField() { result = unique( | | u.getACanonicalField()).getAField() }
/** Gets a field of the underlying union of this `UnionContent`, if any. */
override Field getAField() { result = u.getAField() and getFieldSize(result) = bytes }
override Field getAField() {
exists(CanonicalField cf |
cf = u.getACanonicalField() and
result = cf.getAField() and
getFieldSize(cf) = bytes
)
}
/** Gets the underlying union of this `UnionContent`. */
Union getUnion() { result = u }
Union getUnion() { result = u.getAUnion() }
/** Gets the indirection index of this `UnionContent`. */
override int getIndirectionIndex() { result = indirectionIndex }
override predicate impliesClearOf(Content c) {
exists(UnionContent uc |
uc = c and
uc.getUnion() = u and
exists(int i |
c = TUnionContent(u, _, i) and
// If `this` is `u` then `c` is cleared if it's of the
// form `*u`, `**u`, etc. (and we ignore `bytes` because
// we know the entire union is overwritten because it's a
// union).
uc.getIndirectionIndex() >= indirectionIndex
i >= indirectionIndex
)
}
}

View File

@@ -1,3 +1,4 @@
/*- Compilations -*/
/**
@@ -2378,6 +2379,24 @@ link_parent(
int link_target : @link_target ref
);
/**
* The CLI will automatically emit applicable tuples for this table,
* such as `databaseMetadata("isOverlay", "true")` when building an
* overlay database.
*/
databaseMetadata(
string metadataKey: string ref,
string value: string ref
);
/**
* The CLI will automatically emit tuples for each new/modified/deleted file
* when building an overlay database.
*/
overlayChangedFiles(
string path: string ref
);
/*- XML Files -*/
xmlEncoding(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add databaseMetadata and overlayChangedFiles relations
compatibility: full

View File

@@ -142,6 +142,7 @@ postWithInFlow
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:118:7:118:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:124:5:124:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:167:9:167:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -308,3 +308,5 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
| simple.cpp:124:5:124:6 | * ... | AST only |
| simple.cpp:131:14:131:14 | a | IR only |
| simple.cpp:136:10:136:10 | a | IR only |
| simple.cpp:167:9:167:9 | x | AST only |
| simple.cpp:168:8:168:12 | u_int | IR only |

View File

@@ -670,6 +670,8 @@
| simple.cpp:131:14:131:14 | a |
| simple.cpp:135:20:135:20 | q |
| simple.cpp:136:10:136:10 | a |
| simple.cpp:167:3:167:7 | u_int |
| simple.cpp:168:8:168:12 | u_int |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -597,6 +597,8 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
| simple.cpp:118:7:118:7 | i |
| simple.cpp:124:5:124:6 | * ... |
| simple.cpp:135:20:135:20 | q |
| simple.cpp:167:3:167:7 | u_int |
| simple.cpp:167:9:167:9 | x |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -136,4 +136,36 @@ void alias_with_fields(bool b) {
sink(a.i); // $ MISSING: ast,ir
}
template<typename T>
union U_with_two_instantiations_of_different_size {
int x;
T y;
};
struct LargeStruct {
int data[64];
};
void test_union_with_two_instantiations_of_different_sizes() {
// A union's fields is partitioned into "chunks" for field-flow in order to
// improve performance (so that a write to a field of a union does not flow
// to too many reads that don't happen at runtime). The partitioning is based
// the size of the types in the union. So a write to a field of size k only
// flows to a read of size k.
// Since field-flow is based on uninstantiated types a field can have
// multiple sizes if the union is instantiated with types of
// different sizes. So to compute the partition we pick the maximum size.
// Because of this there are `Content`s corresponding to the union
// `U_with_two_instantiations_of_different_size<T>`: The one for size
// `sizeof(int)`, and the one for size `sizeof(LargeStruct)` (because
// `LargeStruct` is larger than `int`). So the write to `x` writes to the
// `Content` for size `sizeof(int)`, and the read of `y` reads from the
// `Content` for size `sizeof(LargeStruct)`.
U_with_two_instantiations_of_different_size<int> u_int;
U_with_two_instantiations_of_different_size<LargeStruct> u_very_large;
u_int.x = user_input();
sink(u_int.y); // $ MISSING: ir
}
} // namespace Simple

View File

@@ -2,10 +2,10 @@
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | address && | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const __va_list_tag & | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const address & | SemanticStackVariable | | |
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | Field | | |
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | Field | | |
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | Field | | |
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | Field | | |
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | NonLocalCanonicalField | | |
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | NonLocalCanonicalField | | |
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | NonLocalCanonicalField | | |
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | NonLocalCanonicalField | | |
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
@@ -33,10 +33,10 @@
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | LocalVariable, SemanticStackVariable | | |
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | GlobalLikeVariable, StaticLocalVariable | | static |
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | Field | | |
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | NonLocalCanonicalField | | |
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable, StaticStorageDurationVariable | | static |
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
| variables.cpp:60:10:60:17 | __func__ | file://:0:0:0:0 | const char[9] | GlobalLikeVariable, StaticInitializedStaticLocalVariable | | static |

View File

@@ -12,6 +12,7 @@ ql/go/ql/src/Security/CWE-079/HtmlTemplateEscapingBypassXss.ql
ql/go/ql/src/Security/CWE-079/ReflectedXss.ql
ql/go/ql/src/Security/CWE-089/SqlInjection.ql
ql/go/ql/src/Security/CWE-089/StringBreak.ql
ql/go/ql/src/Security/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql
ql/go/ql/src/Security/CWE-209/StackTraceExposure.ql
ql/go/ql/src/Security/CWE-295/DisabledCertificateCheck.ql
@@ -26,6 +27,7 @@ ql/go/ql/src/Security/CWE-347/MissingJwtSignatureCheck.ql
ql/go/ql/src/Security/CWE-352/ConstantOauth2State.ql
ql/go/ql/src/Security/CWE-601/BadRedirectCheck.ql
ql/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql
ql/go/ql/src/Security/CWE-614/CookieWithoutSecure.ql
ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

View File

@@ -34,6 +34,7 @@ ql/go/ql/src/Security/CWE-079/HtmlTemplateEscapingBypassXss.ql
ql/go/ql/src/Security/CWE-079/ReflectedXss.ql
ql/go/ql/src/Security/CWE-089/SqlInjection.ql
ql/go/ql/src/Security/CWE-089/StringBreak.ql
ql/go/ql/src/Security/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/Security/CWE-117/LogInjection.ql
ql/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql
ql/go/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -49,6 +50,7 @@ ql/go/ql/src/Security/CWE-347/MissingJwtSignatureCheck.ql
ql/go/ql/src/Security/CWE-352/ConstantOauth2State.ql
ql/go/ql/src/Security/CWE-601/BadRedirectCheck.ql
ql/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql
ql/go/ql/src/Security/CWE-614/CookieWithoutSecure.ql
ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

View File

@@ -12,6 +12,7 @@ ql/go/ql/src/Security/CWE-079/HtmlTemplateEscapingBypassXss.ql
ql/go/ql/src/Security/CWE-079/ReflectedXss.ql
ql/go/ql/src/Security/CWE-089/SqlInjection.ql
ql/go/ql/src/Security/CWE-089/StringBreak.ql
ql/go/ql/src/Security/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/Security/CWE-117/LogInjection.ql
ql/go/ql/src/Security/CWE-190/AllocationSizeOverflow.ql
ql/go/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -27,6 +28,7 @@ ql/go/ql/src/Security/CWE-347/MissingJwtSignatureCheck.ql
ql/go/ql/src/Security/CWE-352/ConstantOauth2State.ql
ql/go/ql/src/Security/CWE-601/BadRedirectCheck.ql
ql/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql
ql/go/ql/src/Security/CWE-614/CookieWithoutSecure.ql
ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql

View File

@@ -9,7 +9,6 @@ ql/go/ql/src/Security/CWE-079/StoredXss.ql
ql/go/ql/src/Security/CWE-798/HardcodedCredentials.ql
ql/go/ql/src/definitions.ql
ql/go/ql/src/experimental/CWE-090/LDAPInjection.ql
ql/go/ql/src/experimental/CWE-1004/CookieWithoutHttpOnly.ql
ql/go/ql/src/experimental/CWE-203/Timing.ql
ql/go/ql/src/experimental/CWE-285/PamAuthBypass.ql
ql/go/ql/src/experimental/CWE-287/ImproperLdapAuth.ql

View File

@@ -41,6 +41,7 @@ import semmle.go.frameworks.ElazarlGoproxy
import semmle.go.frameworks.Email
import semmle.go.frameworks.Encoding
import semmle.go.frameworks.Fasthttp
import semmle.go.frameworks.Gin
import semmle.go.frameworks.GinCors
import semmle.go.frameworks.Glog
import semmle.go.frameworks.GoJose

View File

@@ -380,4 +380,96 @@ module Http {
/** Gets a node that is used in a check that is tested before this handler is run. */
predicate guardedBy(DataFlow::Node check) { super.guardedBy(check) }
}
/** Provides a class for modeling new HTTP response cookie write APIs. */
module CookieWrite {
/**
* A write of an HTTP Cookie to an HTTP response.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `HTTP::CookieWrite` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the name of the cookie written. */
abstract DataFlow::Node getName();
/** Gets the value of the cookie written. */
abstract DataFlow::Node getValue();
/** Gets the `Secure` attribute of the cookie written. */
abstract DataFlow::Node getSecure();
/** Gets the `HttpOnly` attribute of the cookie written. */
abstract DataFlow::Node getHttpOnly();
}
}
/**
* A write of an HTTP Cookie to an HTTP response.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::CookieWrite::Range` instead.
*/
class CookieWrite extends DataFlow::Node instanceof CookieWrite::Range {
/** Gets the name of the cookie written. */
DataFlow::Node getName() { result = super.getName() }
/** Gets the value of the cookie written. */
DataFlow::Node getValue() { result = super.getValue() }
/** Gets the `Secure` attribute of the cookie written. */
DataFlow::Node getSecure() { result = super.getSecure() }
/** Gets the `HttpOnly` attribute of the cookie written. */
DataFlow::Node getHttpOnly() { result = super.getHttpOnly() }
}
/** Provides a class for modeling the new APIs for writes to options of an HTTP cookie. */
module CookieOptionWrite {
/**
* A write to an option of an HTTP cookie object.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `HTTP::CookieOptionWrite` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the node representing the cookie object for the options being set. */
abstract DataFlow::Node getCookieOutput();
/** Gets the name of the cookie represented, if any. */
abstract DataFlow::Node getName();
/** Gets the value of the cookie represented, if any. */
abstract DataFlow::Node getValue();
/** Gets the `Secure` attribute of the cookie represented, if any. */
abstract DataFlow::Node getSecure();
/** Gets the `HttpOnly` attribute of the cookie represented, if any. */
abstract DataFlow::Node getHttpOnly();
}
}
/**
* A write to an option of an HTTP cookie object.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::CookieOptionWrite::Range` instead.
*/
class CookieOptionWrite extends DataFlow::Node instanceof CookieOptionWrite::Range {
/** Gets the node representing the cookie object for the options being set. */
DataFlow::Node getCookieOutput() { result = super.getCookieOutput() }
/** Gets the name of the cookie represented, if any. */
DataFlow::Node getName() { result = super.getName() }
/** Gets the value of the cookie represented, if any. */
DataFlow::Node getValue() { result = super.getValue() }
/** Gets the `Secure` attribute of the cookie represented, if any. */
DataFlow::Node getSecure() { result = super.getSecure() }
/** Gets the `HttpOnly` attribute of the cookie represented, if any. */
DataFlow::Node getHttpOnly() { result = super.getHttpOnly() }
}
}

View File

@@ -0,0 +1,24 @@
/**
* Provides classes for modeling the `github.com/gin-gonic/gin` package.
*/
import go
import semmle.go.concepts.HTTP
/** Provides models for the `gin-gonic/gin` package. */
module Gin {
/** Gets the package name `github.com/gin-gonic/gin`. */
string packagePath() { result = package("github.com/gin-gonic/gin", "") }
private class GinCookieWrite extends Http::CookieWrite::Range, DataFlow::MethodCallNode {
GinCookieWrite() { this.getTarget().hasQualifiedName(packagePath(), "Context", "SetCookie") }
override DataFlow::Node getName() { result = this.getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override DataFlow::Node getSecure() { result = this.getArgument(5) }
override DataFlow::Node getHttpOnly() { result = this.getArgument(6) }
}
}

View File

@@ -293,4 +293,38 @@ module NetHttp {
override DataFlow::Node getAPathArgument() { result = this.getArgument(2) }
}
private class CookieWrite extends Http::CookieWrite::Range, DataFlow::CallNode {
CookieWrite() { this.getTarget().hasQualifiedName(package("net/http", ""), "SetCookie") }
override DataFlow::Node getName() { result = this.getArgument(1) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override DataFlow::Node getSecure() { result = this.getArgument(1) }
override DataFlow::Node getHttpOnly() { result = this.getArgument(1) }
}
private class CookieFieldWrite extends Http::CookieOptionWrite::Range {
DataFlow::Node written;
string fieldName;
CookieFieldWrite() {
exists(Write w, Field f |
f.hasQualifiedName(package("net/http", ""), "Cookie", fieldName) and
w.writesField(this, f, written)
)
}
override DataFlow::Node getCookieOutput() { result = this }
override DataFlow::Node getName() { fieldName = "Name" and result = written }
override DataFlow::Node getValue() { fieldName = "Value" and result = written }
override DataFlow::Node getSecure() { fieldName = "Secure" and result = written }
override DataFlow::Node getHttpOnly() { fieldName = "HttpOnly" and result = written }
}
}

View File

@@ -0,0 +1,77 @@
/** Provides classes and predicates for identifying HTTP cookies without the `HttpOnly` attribute. */
import go
import semmle.go.concepts.HTTP
import semmle.go.dataflow.DataFlow
private module SensitiveCookieNameConfig implements DataFlow::ConfigSig {
/**
* Holds if `source` is an expression with a name or literal value `val` indicating a sensitive cookie.
*/
additional predicate isSource(DataFlow::Node source, string val) {
(
val = source.asExpr().getStringValue() or
val = source.asExpr().(Name).getTarget().getName()
) and
val.regexpMatch("(?i).*(session|login|token|user|auth|credential).*") and
not val.regexpMatch("(?i).*(xsrf|csrf|forgery).*")
}
predicate isSource(DataFlow::Node source) { isSource(source, _) }
additional predicate isSink(DataFlow::Node sink, Http::CookieWrite cw) { sink = cw.getName() }
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getName() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from sensitive names to HTTP cookie writes. */
module SensitiveCookieNameFlow = TaintTracking::Global<SensitiveCookieNameConfig>;
private module BooleanCookieHttpOnlyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { exists(Http::CookieWrite cw | sink = cw.getHttpOnly()) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getHttpOnly() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from boolean expressions to the `HttpOnly` attribute of HTTP cookie writes. */
module BooleanCookieHttpOnlyFlow = TaintTracking::Global<BooleanCookieHttpOnlyConfig>;
/** Holds if `cw` has the `HttpOnly` attribute left at its default value of `false`. */
predicate isNonHttpOnlyDefault(Http::CookieWrite cw) {
not BooleanCookieHttpOnlyFlow::flowTo(cw.getHttpOnly())
}
/** Holds if `cw` has the `HttpOnly` attribute explicitly set to `false`, from the expression `boolFalse`. */
predicate isNonHttpOnlyDirect(Http::CookieWrite cw, Expr boolFalse) {
BooleanCookieHttpOnlyFlow::flow(DataFlow::exprNode(boolFalse), cw.getHttpOnly()) and
boolFalse.getBoolValue() = false
}
/** Holds if `cw` has the `HttpOnly` attribute set to `false`, either explicitly or by default. */
predicate isNonHttpOnlyCookie(Http::CookieWrite cw) {
isNonHttpOnlyDefault(cw) or
isNonHttpOnlyDirect(cw, _)
}
/**
* Holds if `cw` has the sensitive name `name`, from the expression `nameExpr`.
* `source` and `sink` represent the data flow path from the sensitive name expression to the cookie write.
*/
predicate isSensitiveCookie(
Http::CookieWrite cw, string name, SensitiveCookieNameFlow::PathNode source,
SensitiveCookieNameFlow::PathNode sink
) {
SensitiveCookieNameFlow::flowPath(source, sink) and
SensitiveCookieNameConfig::isSource(source.getNode(), name) and
SensitiveCookieNameConfig::isSink(sink.getNode(), cw)
}

View File

@@ -0,0 +1,37 @@
/** Provides classes and predicates for identifying HTTP cookies without the `Secure` attribute. */
import go
import semmle.go.concepts.HTTP
import semmle.go.dataflow.DataFlow
private module BooleanCookieSecureConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { exists(Http::CookieWrite cw | sink = cw.getSecure()) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getSecure() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from boolean expressions to the `Secure` attribute of HTTP cookie writes. */
module BooleanCookieSecureFlow = TaintTracking::Global<BooleanCookieSecureConfig>;
/** Holds if `cw` has the `Secure` attribute left at its default value of `false`. */
predicate isInsecureDefault(Http::CookieWrite cw) {
not BooleanCookieSecureFlow::flowTo(cw.getSecure())
}
/** Holds if `cw` has the `Secure` attribute explicitly set to `false`, from the expression `boolFalse`. */
predicate isInsecureDirect(Http::CookieWrite cw, Expr boolFalse) {
BooleanCookieSecureFlow::flow(DataFlow::exprNode(boolFalse), cw.getSecure()) and
boolFalse.getBoolValue() = false
}
/** Holds if `cw` has the `Secure` attribute set to `false`, either explicitly or by default. */
predicate isInsecureCookie(Http::CookieWrite cw) {
isInsecureDefault(cw) or
isInsecureDirect(cw, _)
}

View File

@@ -0,0 +1,34 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Cookies without the <code>HttpOnly</code> flag set are accessible to client-side scripts such as JavaScript running in the same origin.
In case of a Cross-Site Scripting (XSS) vulnerability, the cookie can be stolen by a malicious script.
If a sensitive cookie does not need to be accessed directly by client-side JS, the <code>HttpOnly</code> flag should be set.</p>
</overview>
<recommendation>
<p>
Set the <code>HttpOnly</code> flag to <code>true</code> for authentication cookies to ensure they are not accessible to client-side scripts.
</p>
</recommendation>
<example>
<p>
In the following example, in the case marked BAD, the <code>HttpOnly</code> flag is not set, so the default value of <code>false</code> is used.
In the case marked GOOD, the <code>HttpOnly</code> flag is set to <code>true</code>.
</p>
<sample src="examples/CookieWithoutHttpOnly.go"/>
</example>
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header.</li>
<li>PortSwigger: <a href="https://portswigger.net/kb/issues/00500600_cookie-without-httponly-flag-set">Cookie without HttpOnly flag set</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,25 @@
/**
* @name Cookie 'HttpOnly' attribute is not set to true
* @description Sensitive cookies without the `HttpOnly` property set are accessible by client-side scripts such as JavaScript.
* This makes them more vulnerable to being stolen by an XSS attack.
* @kind path-problem
* @problem.severity warning
* @precision high
* @security-severity 5.0
* @id go/cookie-httponly-not-set
* @tags security
* external/cwe/cwe-1004
*/
import go
import semmle.go.security.CookieWithoutHttpOnly
import SensitiveCookieNameFlow::PathGraph
from
Http::CookieWrite cw, string name, SensitiveCookieNameFlow::PathNode source,
SensitiveCookieNameFlow::PathNode sink
where
isSensitiveCookie(cw, name, source, sink) and
isNonHttpOnlyCookie(cw)
select cw, source, sink, "Sensitive cookie $@ does not set HttpOnly attribute to true.", source,
name

View File

@@ -0,0 +1,22 @@
package main
import (
"net/http"
)
func handlerBad(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: The HttpOnly flag is set to false by default.
}
func handlerGood(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: The HttpOnly flag is set to true.
}

View File

@@ -0,0 +1,35 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Cookies without the <code>Secure</code> flag set may be transmitted using HTTP instead of HTTPS.
This leaves them vulnerable to being read by a third party attacker. If a sensitive cookie such as a session
key is intercepted this way, it would allow the attacker to perform actions on a user's behalf.</p>
</overview>
<recommendation>
<p>
Set the <code>Secure</code> flag to <code>true</code> to ensure cookies are only transmitted over secure HTTPS connections.
</p>
</recommendation>
<example>
<p>
In the following example, in the case marked BAD, the <code>Secure</code> flag is set to <code>false</code> by default.
In the case marked GOOD, the <code>Secure</code> flag is set to <code>true</code>.
</p>
<sample src="examples/CookieWithoutSecure.go"/>
</example>
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header.</li>
<li>Detectify: <a href="https://support.detectify.com/support/solutions/articles/48001048982-cookie-lack-secure-flag">Cookie lack Secure flag</a>.</li>
<li>PortSwigger: <a href="https://portswigger.net/kb/issues/00500200_tls-cookie-without-secure-flag-set">TLS cookie without secure flag set</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,19 @@
/**
* @name Cookie 'Secure' attribute is not set to true
* @description Cookies without the `Secure` flag may be sent in cleartext.
* This makes them vulnerable to be intercepted by an attacker.
* @kind problem
* @problem.severity warning
* @precision high
* @security-severity 4.0
* @id go/cookie-secure-not-set
* @tags security
* external/cwe/cwe-614
*/
import go
import semmle.go.security.CookieWithoutSecure
from Http::CookieWrite cw
where isInsecureCookie(cw)
select cw, "Cookie does not set Secure attribute to true."

View File

@@ -0,0 +1,22 @@
package main
import (
"net/http"
)
func handlerBad(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: The Secure flag is set to false by default.
}
func handlerGood(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
Secure: true,
}
http.SetCookie(w, &c) // GOOD: The Secure flag is set to true.
}

View File

@@ -0,0 +1,5 @@
---
category: newQuery
---
* The `go/cookie-http-only-not-set` query has been promoted from the experimental query pack. This query was originally contributed to the experimental query pack by @edvraa.
* A new query `go/cookie-secure-not-set` has been added to detect cookies without the `Secure` flag set.

View File

@@ -1,245 +0,0 @@
import go
private class NetHttpCookieType extends Type {
NetHttpCookieType() { this.hasQualifiedName(package("net/http", ""), "Cookie") }
}
private class GinContextSetCookieMethod extends Method {
GinContextSetCookieMethod() {
this.hasQualifiedName(package("github.com/gin-gonic/gin", ""), "Context", "SetCookie")
}
}
private class GorillaSessionOptionsField extends Field {
GorillaSessionOptionsField() {
this.hasQualifiedName(package("github.com/gorilla/sessions", ""), "Session", "Options")
}
}
/**
* A simplistic points-to alternative: given a struct creation and a field name, get the values that field can be assigned.
*
* Assumptions:
* - we don't reassign the variable that the creation is stored in
* - we always access the creation through the same variable it is initially assigned to
*
* This should cover most typical patterns...
*/
private DataFlow::Node getValueForFieldWrite(StructLit sl, string field) {
exists(Write w, DataFlow::Node base, Field f |
f.getName() = field and
w.writesFieldPreUpdate(base, f, result) and
(
sl = base.asExpr()
or
base.asExpr() instanceof VariableName and
base.getAPredecessor*().asExpr() = sl
)
)
}
/**
* Holds if the expression or its value has a sensitive name
*/
private predicate isAuthVariable(Expr expr) {
exists(string val |
(
val = expr.getStringValue() or
val = expr.(Name).getTarget().getName()
) and
val.regexpMatch("(?i).*(session|login|token|user|auth|credential).*") and
not val.regexpMatch("(?i).*(xsrf|csrf|forgery).*")
)
}
/**
* A cookie passed as the second parameter to `net/http.SetCookie`.
*/
private class SetCookieSink extends DataFlow::Node {
SetCookieSink() {
exists(DataFlow::CallNode cn |
cn.getTarget().hasQualifiedName(package("net/http", ""), "SetCookie") and
this = cn.getArgument(1)
)
}
}
private module NameToNetHttpCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(StructLit sl |
sl.getType() instanceof NetHttpCookieType and
getValueForFieldWrite(sl, "Name") = pred and
sl = succ.asExpr()
)
}
}
/** Tracks taint flow from sensitive names to `net/http.SetCookie`. */
module NameToNetHttpCookieTrackingFlow = TaintTracking::Global<NameToNetHttpCookieTrackingConfig>;
private module BoolToNetHttpCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(StructLit sl |
sl.getType() instanceof NetHttpCookieType and
getValueForFieldWrite(sl, "HttpOnly") = pred and
sl = succ.asExpr()
)
}
}
/**
* Tracks taint flow from a `bool` assigned to `HttpOnly` to
* `net/http.SetCookie`.
*/
module BoolToNetHttpCookieTrackingFlow = TaintTracking::Global<BoolToNetHttpCookieTrackingConfig>;
private module BoolToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.getBoolValue() = false }
predicate isSink(DataFlow::Node sink) {
exists(DataFlow::MethodCallNode mcn |
mcn.getTarget() instanceof GinContextSetCookieMethod and
mcn.getArgument(6) = sink and
exists(DataFlow::Node nameArg |
NameToGinSetCookieTrackingFlow::flowTo(nameArg) and
mcn.getArgument(0) = nameArg
)
)
}
predicate observeDiffInformedIncrementalMode() {
any() // Merged with other flows in CookieWithoutHttpOnly.ql
}
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
/**
* Tracks data flow from `HttpOnly` set to `false` to
* `gin-gonic/gin.Context.SetCookie`.
*/
module BoolToGinSetCookieTrackingFlow = DataFlow::Global<BoolToGinSetCookieTrackingConfig>;
private module NameToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isAuthVariable(source.asExpr()) }
predicate isSink(DataFlow::Node sink) {
exists(DataFlow::MethodCallNode mcn |
mcn.getTarget() instanceof GinContextSetCookieMethod and
mcn.getArgument(0) = sink
)
}
}
/**
* Tracks taint flow from sensitive names to `gin-gonic/gin.Context.SetCookie`.
*/
private module NameToGinSetCookieTrackingFlow = DataFlow::Global<NameToGinSetCookieTrackingConfig>;
/**
* The receiver of `gorilla/sessions.Session.Save` call.
*/
private class GorillaSessionSaveSink extends DataFlow::Node {
GorillaSessionSaveSink() {
exists(DataFlow::MethodCallNode mcn |
this = mcn.getReceiver() and
mcn.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "Session", "Save")
)
}
}
private class GorillaStoreSaveSink extends DataFlow::Node {
GorillaStoreSaveSink() {
exists(DataFlow::MethodCallNode mcn |
this = mcn.getArgument(2) and
mcn.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "CookieStore", "Save")
)
}
}
private module GorillaCookieStoreSaveTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source
.(DataFlow::CallNode)
.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "NewCookieStore")
}
predicate isSink(DataFlow::Node sink) {
sink instanceof GorillaSessionSaveSink or
sink instanceof GorillaStoreSaveSink
}
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::MethodCallNode cn |
cn.getTarget()
.hasQualifiedName(package("github.com/gorilla/sessions", ""), "CookieStore", "Get") and
pred = cn.getReceiver() and
succ = cn.getResult(0)
)
}
}
/**
* Tracks data flow from gorilla cookie store creation to
* `gorilla/sessions.Session.Save`.
*/
module GorillaCookieStoreSaveTrackingFlow = DataFlow::Global<GorillaCookieStoreSaveTrackingConfig>;
private module GorillaSessionOptionsTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(StructLit sl |
sl.getType().hasQualifiedName(package("github.com/gorilla/sessions", ""), "Options") and
source.asExpr() = sl
)
}
predicate isSink(DataFlow::Node sink) { sink instanceof GorillaSessionSaveSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(GorillaSessionOptionsField f, DataFlow::Write w | w.writesField(succ, f, pred))
}
}
/**
* Tracks taint flow from session options to
* `gorilla/sessions.Session.Save`.
*/
module GorillaSessionOptionsTrackingFlow =
TaintTracking::Global<GorillaSessionOptionsTrackingConfig>;
private module BoolToGorillaSessionOptionsTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { sink instanceof GorillaSessionSaveSink }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(StructLit sl |
getValueForFieldWrite(sl, "HttpOnly") = pred and
sl = succ.asExpr()
)
or
exists(GorillaSessionOptionsField f, DataFlow::Write w | w.writesField(succ, f, pred))
}
}
/**
* Tracks taint flow from a `bool` assigned to `HttpOnly` to
* `gorilla/sessions.Session.Save`.
*/
module BoolToGorillaSessionOptionsTrackingFlow =
TaintTracking::Global<BoolToGorillaSessionOptionsTrackingConfig>;

View File

@@ -1,42 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Cookies without <code>HttpOnly</code> attribute are accessible to JavaScript running in the same origin. In case of
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script.
</p>
</overview>
<recommendation>
<p>
Protect sensitive cookies, such as related to authentication, by setting <code>HttpOnly</code> to <code>true</code> to make
them not accessible to JavaScript.
</p>
</recommendation>
<example>
<p>
In the following example the default <code>HttpOnly</code> value is <code>false</code>.
</p>
<sample src="CookieWithoutHttpOnlyBad.go" />
<p>
In the example below <code>HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="CookieWithoutHttpOnlyGood.go" />
</example>
<references>
<li><a href="https://golang.org/pkg/net/http/#Cookie">type Cookie,</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header,</li>
</references>
</qhelp>

View File

@@ -1,99 +0,0 @@
/**
* @name 'HttpOnly' attribute is not set to true
* @description Omitting the 'HttpOnly' attribute for security sensitive data allows
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
* 'HttpOnly' to 'true' to authentication related cookie to make it
* not accessible by JavaScript.
* @kind path-problem
* @problem.severity warning
* @precision high
* @id go/cookie-httponly-not-set
* @tags security
* experimental
* external/cwe/cwe-1004
*/
import go
import AuthCookie
module NetHttpCookieTrackingFlow =
DataFlow::MergePathGraph<NameToNetHttpCookieTrackingFlow::PathNode,
BoolToNetHttpCookieTrackingFlow::PathNode, NameToNetHttpCookieTrackingFlow::PathGraph,
BoolToNetHttpCookieTrackingFlow::PathGraph>;
module GorillaTrackingFlow =
DataFlow::MergePathGraph3<GorillaCookieStoreSaveTrackingFlow::PathNode,
GorillaSessionOptionsTrackingFlow::PathNode, BoolToGorillaSessionOptionsTrackingFlow::PathNode,
GorillaCookieStoreSaveTrackingFlow::PathGraph, GorillaSessionOptionsTrackingFlow::PathGraph,
BoolToGorillaSessionOptionsTrackingFlow::PathGraph>;
module MergedFlow =
DataFlow::MergePathGraph3<NetHttpCookieTrackingFlow::PathNode,
BoolToGinSetCookieTrackingFlow::PathNode, GorillaTrackingFlow::PathNode,
NetHttpCookieTrackingFlow::PathGraph, BoolToGinSetCookieTrackingFlow::PathGraph,
GorillaTrackingFlow::PathGraph>;
import MergedFlow::PathGraph
/** Holds if `HttpOnly` of `net/http.SetCookie` is set to `false` or not set (default value is used). */
predicate isNetHttpCookieFlow(
NetHttpCookieTrackingFlow::PathNode source, NetHttpCookieTrackingFlow::PathNode sink
) {
exists(
NameToNetHttpCookieTrackingFlow::PathNode sensitiveName,
NameToNetHttpCookieTrackingFlow::PathNode setCookieSink
|
NameToNetHttpCookieTrackingFlow::flowPath(sensitiveName, setCookieSink) and
(
not BoolToNetHttpCookieTrackingFlow::flowTo(sink.getNode()) and
source.asPathNode1() = sensitiveName and
sink.asPathNode1() = setCookieSink
or
BoolToNetHttpCookieTrackingFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and
source.getNode().getBoolValue() = false and
setCookieSink.getNode() = sink.getNode()
)
)
}
/**
* Holds if there is gorilla cookie store creation to `Save` path and
* `HttpOnly` is set to `false` or not set (default value is used).
*/
predicate isGorillaSessionsCookieFlow(
GorillaTrackingFlow::PathNode source, GorillaTrackingFlow::PathNode sink
) {
exists(
GorillaCookieStoreSaveTrackingFlow::PathNode cookieStoreCreate,
GorillaCookieStoreSaveTrackingFlow::PathNode sessionSave
|
GorillaCookieStoreSaveTrackingFlow::flowPath(cookieStoreCreate, sessionSave) and
(
not GorillaSessionOptionsTrackingFlow::flowTo(sink.getNode()) and
source.asPathNode1() = cookieStoreCreate and
sink.asPathNode1() = sessionSave
or
exists(GorillaTrackingFlow::PathNode options, GorillaTrackingFlow::PathNode sessionSave2 |
GorillaSessionOptionsTrackingFlow::flowPath(options.asPathNode2(),
sessionSave2.asPathNode2()) and
(
not BoolToGorillaSessionOptionsTrackingFlow::flowTo(sink.getNode()) and
sink = sessionSave2 and
source = options and
sessionSave.getNode() = sessionSave2.getNode()
or
BoolToGorillaSessionOptionsTrackingFlow::flowPath(source.asPathNode3(), sink.asPathNode3()) and
source.getNode().getBoolValue() = false and
sink.getNode() = sessionSave.getNode()
)
)
)
)
}
from MergedFlow::PathNode source, MergedFlow::PathNode sink
where
isNetHttpCookieFlow(source.asPathNode1(), sink.asPathNode1()) or
BoolToGinSetCookieTrackingFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) or
isGorillaSessionsCookieFlow(source.asPathNode3(), sink.asPathNode3())
select sink.getNode(), source, sink, "Cookie attribute 'HttpOnly' is not set to true."

View File

@@ -1,17 +0,0 @@
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c)
}
func main() {
http.HandleFunc("/", handler)
}

View File

@@ -1,18 +0,0 @@
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c)
}
func main() {
http.HandleFunc("/", handler)
}

View File

@@ -1,432 +0,0 @@
edges
| CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | CookieWithoutHttpOnly.go:15:20:15:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | CookieWithoutHttpOnly.go:15:21:15:21 | c | provenance | |
| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | CookieWithoutHttpOnly.go:15:20:15:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:15:21:15:21 | c | CookieWithoutHttpOnly.go:15:20:15:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:15:21:15:21 | c | CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:21:24:21 | c | provenance | |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | CookieWithoutHttpOnly.go:24:21:24:21 | c | provenance | |
| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:21:33:21 | c | provenance | |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | CookieWithoutHttpOnly.go:33:21:33:21 | c | provenance | |
| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:31:13:31:16 | true | CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:21:42:21 | c | provenance | |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | CookieWithoutHttpOnly.go:42:21:42:21 | c | provenance | |
| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:41:15:41:18 | true | CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:21:51:21 | c | provenance | |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | CookieWithoutHttpOnly.go:51:21:51:21 | c | provenance | |
| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | CookieWithoutHttpOnly.go:59:13:59:15 | val | provenance | |
| CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:59:13:59:15 | val | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:21:61:21 | c | provenance | |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | CookieWithoutHttpOnly.go:61:21:61:21 | c | provenance | |
| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:59:13:59:15 | val | CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | CookieWithoutHttpOnly.go:69:13:69:15 | val | provenance | |
| CookieWithoutHttpOnly.go:65:9:65:12 | true | CookieWithoutHttpOnly.go:69:13:69:15 | val | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:21:71:21 | c | provenance | |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | CookieWithoutHttpOnly.go:71:21:71:21 | c | provenance | |
| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:69:13:69:15 | val | CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | CookieWithoutHttpOnly.go:80:15:80:17 | val | provenance | |
| CookieWithoutHttpOnly.go:75:9:75:12 | true | CookieWithoutHttpOnly.go:80:15:80:17 | val | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:21:81:21 | c | provenance | |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | CookieWithoutHttpOnly.go:81:21:81:21 | c | provenance | |
| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:80:15:80:17 | val | CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | CookieWithoutHttpOnly.go:90:15:90:17 | val | provenance | |
| CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:90:15:90:17 | val | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:21:91:21 | c | provenance | |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | CookieWithoutHttpOnly.go:91:21:91:21 | c | provenance | |
| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:90:15:90:17 | val | CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | CookieWithoutHttpOnly.go:100:20:100:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | CookieWithoutHttpOnly.go:100:21:100:21 | c | provenance | |
| CookieWithoutHttpOnly.go:99:15:99:19 | false | CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | CookieWithoutHttpOnly.go:100:20:100:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:100:21:100:21 | c | CookieWithoutHttpOnly.go:100:20:100:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:100:21:100:21 | c | CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | CookieWithoutHttpOnly.go:106:10:106:13 | name | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:21:110:21 | c | provenance | |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | CookieWithoutHttpOnly.go:110:21:110:21 | c | provenance | |
| CookieWithoutHttpOnly.go:106:10:106:13 | name | CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | CookieWithoutHttpOnly.go:116:10:116:16 | session | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:21:120:21 | c | provenance | |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | CookieWithoutHttpOnly.go:120:21:120:21 | c | provenance | |
| CookieWithoutHttpOnly.go:116:10:116:16 | session | CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:126:16:126:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:134:16:134:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:146:16:146:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:158:16:158:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:170:16:170:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:183:16:183:20 | store | provenance | |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:195:16:195:20 | store | provenance | |
| CookieWithoutHttpOnly.go:126:2:126:43 | ... := ...[0] | CookieWithoutHttpOnly.go:129:2:129:8 | session | provenance | |
| CookieWithoutHttpOnly.go:126:16:126:20 | store | CookieWithoutHttpOnly.go:126:2:126:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:134:2:134:43 | ... := ...[0] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:134:16:134:20 | store | CookieWithoutHttpOnly.go:134:2:134:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:142:2:142:8 | session | provenance | |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:137:20:140:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | CookieWithoutHttpOnly.go:137:20:140:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:146:2:146:43 | ... := ...[0] | CookieWithoutHttpOnly.go:153:2:153:8 | session | provenance | |
| CookieWithoutHttpOnly.go:146:16:146:20 | store | CookieWithoutHttpOnly.go:146:2:146:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | CookieWithoutHttpOnly.go:153:2:153:8 | session | provenance | |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:153:2:153:8 | session | provenance | |
| CookieWithoutHttpOnly.go:149:20:151:2 | &... | CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:149:20:151:2 | &... | CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:149:20:151:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:157:14:157:17 | true | CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:158:2:158:43 | ... := ...[0] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:158:16:158:20 | store | CookieWithoutHttpOnly.go:158:2:158:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:166:2:166:8 | session | provenance | |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:161:20:164:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | CookieWithoutHttpOnly.go:161:20:164:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | provenance | |
| CookieWithoutHttpOnly.go:170:2:170:43 | ... := ...[0] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:170:16:170:20 | store | CookieWithoutHttpOnly.go:170:2:170:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | CookieWithoutHttpOnly.go:178:2:178:8 | session | provenance | |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | provenance | Config |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:173:20:176:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | CookieWithoutHttpOnly.go:173:20:176:2 | &... | provenance | |
| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:183:2:183:43 | ... := ...[0] | CookieWithoutHttpOnly.go:191:19:191:25 | session | provenance | |
| CookieWithoutHttpOnly.go:183:16:183:20 | store | CookieWithoutHttpOnly.go:183:2:183:43 | ... := ...[0] | provenance | Config |
| CookieWithoutHttpOnly.go:195:2:195:43 | ... := ...[0] | CookieWithoutHttpOnly.go:202:19:202:25 | session | provenance | |
| CookieWithoutHttpOnly.go:195:16:195:20 | store | CookieWithoutHttpOnly.go:195:2:195:43 | ... := ...[0] | provenance | Config |
nodes
| CookieWithoutHttpOnly.go:11:7:14:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:12:10:12:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:15:20:15:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:15:20:15:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:15:21:15:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:19:7:23:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:20:13:20:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:22:13:22:17 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:24:21:24:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:28:7:32:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:29:13:29:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:31:13:31:16 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:33:20:33:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:33:21:33:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:37:7:40:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:38:10:38:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:41:15:41:18 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:42:20:42:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:42:21:42:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:46:7:49:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:47:10:47:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:50:15:50:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:51:21:51:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:55:2:55:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:55:9:55:13 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:56:7:60:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:57:13:57:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:59:13:59:15 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:61:21:61:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:65:2:65:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:65:9:65:12 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:66:7:70:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:67:13:67:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:69:13:69:15 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:71:20:71:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:71:21:71:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:75:2:75:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:75:9:75:12 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:76:7:79:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:77:10:77:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:80:15:80:17 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:81:20:81:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:81:21:81:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:85:2:85:4 | definition of val | semmle.label | definition of val |
| CookieWithoutHttpOnly.go:85:9:85:13 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:86:7:89:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:87:10:87:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:90:15:90:17 | val | semmle.label | val |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:91:21:91:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:95:7:98:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:99:15:99:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:100:20:100:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:100:20:100:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:100:21:100:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:104:10:104:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:105:7:108:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:106:10:106:13 | name | semmle.label | name |
| CookieWithoutHttpOnly.go:109:15:109:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:110:21:110:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:114:13:114:24 | "login_name" | semmle.label | "login_name" |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:115:7:118:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:116:10:116:16 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:119:15:119:19 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:120:21:120:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | semmle.label | call to NewCookieStore |
| CookieWithoutHttpOnly.go:126:2:126:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:126:16:126:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:129:2:129:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:133:2:133:9 | definition of httpOnly | semmle.label | definition of httpOnly |
| CookieWithoutHttpOnly.go:133:14:133:18 | false | semmle.label | false |
| CookieWithoutHttpOnly.go:134:2:134:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:134:16:134:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:137:2:137:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:137:20:140:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:137:21:140:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:139:13:139:20 | httpOnly | semmle.label | httpOnly |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:146:2:146:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:146:16:146:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:149:2:149:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:149:2:149:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:149:20:151:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:153:2:153:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:153:2:153:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:157:2:157:9 | definition of httpOnly | semmle.label | definition of httpOnly |
| CookieWithoutHttpOnly.go:157:14:157:17 | true | semmle.label | true |
| CookieWithoutHttpOnly.go:158:2:158:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:158:16:158:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:161:2:161:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:161:20:164:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:161:21:164:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:163:13:163:20 | httpOnly | semmle.label | httpOnly |
| CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:166:2:166:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:169:56:169:63 | argument corresponding to httpOnly | semmle.label | argument corresponding to httpOnly |
| CookieWithoutHttpOnly.go:169:56:169:63 | definition of httpOnly | semmle.label | definition of httpOnly |
| CookieWithoutHttpOnly.go:170:2:170:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:170:16:170:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] | semmle.label | session [postupdate] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:173:2:173:8 | session [postupdate] [pointer] | semmle.label | session [postupdate] [pointer] |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:173:20:176:2 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:173:21:176:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:175:13:175:20 | httpOnly | semmle.label | httpOnly |
| CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:178:2:178:8 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:183:2:183:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:183:16:183:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:191:19:191:25 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:195:2:195:43 | ... := ...[0] | semmle.label | ... := ...[0] |
| CookieWithoutHttpOnly.go:195:16:195:20 | store | semmle.label | store |
| CookieWithoutHttpOnly.go:202:19:202:25 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:214:66:214:70 | false | semmle.label | false |
subpaths
#select
| CookieWithoutHttpOnly.go:15:20:15:21 | &... | CookieWithoutHttpOnly.go:12:10:12:18 | "session" | CookieWithoutHttpOnly.go:15:20:15:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:24:20:24:21 | &... | CookieWithoutHttpOnly.go:22:13:22:17 | false | CookieWithoutHttpOnly.go:24:20:24:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:51:20:51:21 | &... | CookieWithoutHttpOnly.go:50:15:50:19 | false | CookieWithoutHttpOnly.go:51:20:51:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:61:20:61:21 | &... | CookieWithoutHttpOnly.go:55:9:55:13 | false | CookieWithoutHttpOnly.go:61:20:61:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:91:20:91:21 | &... | CookieWithoutHttpOnly.go:85:9:85:13 | false | CookieWithoutHttpOnly.go:91:20:91:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:110:20:110:21 | &... | CookieWithoutHttpOnly.go:109:15:109:19 | false | CookieWithoutHttpOnly.go:110:20:110:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:120:20:120:21 | &... | CookieWithoutHttpOnly.go:119:15:119:19 | false | CookieWithoutHttpOnly.go:120:20:120:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:129:2:129:8 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:129:2:129:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:142:2:142:8 | session | CookieWithoutHttpOnly.go:133:14:133:18 | false | CookieWithoutHttpOnly.go:142:2:142:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:153:2:153:8 | session | CookieWithoutHttpOnly.go:149:21:151:2 | struct literal | CookieWithoutHttpOnly.go:153:2:153:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:191:19:191:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:191:19:191:25 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:202:19:202:25 | session | CookieWithoutHttpOnly.go:123:13:123:49 | call to NewCookieStore | CookieWithoutHttpOnly.go:202:19:202:25 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:214:66:214:70 | false | CookieWithoutHttpOnly.go:214:66:214:70 | false | CookieWithoutHttpOnly.go:214:66:214:70 | false | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -1,219 +0,0 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/sessions"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: HttpOnly set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: false,
}
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = true
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler10(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "consent",
Value: "1",
}
c.HttpOnly = false
http.SetCookie(w, &c) // GOOD: Name is not auth related
}
func handler11(w http.ResponseWriter, r *http.Request) {
name := "session"
c := http.Cookie{
Name: name,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: auth related name
}
func handler12(w http.ResponseWriter, r *http.Request) {
session := "login_name"
c := http.Cookie{
Name: session,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: auth related name
}
var store = sessions.NewCookieStore([]byte("aa"))
func handler13(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Save(r, w) // BAD: Default options are set (false)
}
func handler14(w http.ResponseWriter, r *http.Request) {
httpOnly := false
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // BAD: Explicitly set to false
}
func handler15(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
}
session.Save(r, w) // BAD: default (false) is used
}
func handler16(w http.ResponseWriter, r *http.Request) {
httpOnly := true
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // GOOD: value is true
}
func handler17(w http.ResponseWriter, r *http.Request, httpOnly bool) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // GOOD: value is unknown
}
func handler18(w http.ResponseWriter, r *http.Request) {
httpOnly := false
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
store.Save(r, w, session) // BAD: Explicitly set to false
}
func handler19(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
}
store.Save(r, w, session) // BAD: default (false) is used
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // BAD: httpOnly set to false
}
})
router.Run()
}

View File

@@ -1 +0,0 @@
experimental/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,75 +0,0 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gorilla/sessions, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gorilla/sessions (exports: CookieStore; functions: NewCookieStore)
// Package sessions is a stub of github.com/gorilla/sessions, generated by depstubber.
package sessions
import (
http "net/http"
)
type CookieStore struct {
Codecs []interface{}
Options *Options
}
func (_ *CookieStore) Get(_ *http.Request, _ string) (*Session, error) {
return nil, nil
}
func (_ *CookieStore) MaxAge(_ int) {}
func (_ *CookieStore) New(_ *http.Request, _ string) (*Session, error) {
return nil, nil
}
func (_ *CookieStore) Save(_ *http.Request, _ http.ResponseWriter, _ *Session) error {
return nil
}
func NewCookieStore(_ ...[]byte) *CookieStore {
return nil
}
type Options struct {
Path string
Domain string
MaxAge int
Secure bool
HttpOnly bool
SameSite http.SameSite
}
type Session struct {
ID string
Values map[interface{}]interface{}
Options *Options
IsNew bool
}
func (_ *Session) AddFlash(_ interface{}, _ ...string) {}
func (_ *Session) Flashes(_ ...string) []interface{} {
return nil
}
func (_ *Session) Name() string {
return ""
}
func (_ *Session) Save(_ *http.Request, _ http.ResponseWriter) error {
return nil
}
func (_ *Session) Store() Store {
return nil
}
type Store interface {
Get(_ *http.Request, _ string) (*Session, error)
New(_ *http.Request, _ string) (*Session, error)
Save(_ *http.Request, _ http.ResponseWriter, _ *Session) error
}

View File

@@ -1,6 +0,0 @@
# github.com/gin-gonic/gin v1.7.1
## explicit
github.com/gin-gonic/gin
# github.com/gorilla/sessions v1.2.1
## explicit
github.com/gorilla/sessions

View File

@@ -0,0 +1,139 @@
#select
| CookieWithoutHttpOnly.go:14:2:14:22 | call to SetCookie | CookieWithoutHttpOnly.go:11:10:11:18 | "session" | CookieWithoutHttpOnly.go:14:20:14:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:11:10:11:18 | "session" | session |
| CookieWithoutHttpOnly.go:23:2:23:22 | call to SetCookie | CookieWithoutHttpOnly.go:19:13:19:21 | "session" | CookieWithoutHttpOnly.go:23:20:23:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:19:13:19:21 | "session" | session |
| CookieWithoutHttpOnly.go:50:2:50:22 | call to SetCookie | CookieWithoutHttpOnly.go:46:10:46:18 | "session" | CookieWithoutHttpOnly.go:50:20:50:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:46:10:46:18 | "session" | session |
| CookieWithoutHttpOnly.go:60:2:60:22 | call to SetCookie | CookieWithoutHttpOnly.go:56:13:56:21 | "session" | CookieWithoutHttpOnly.go:60:20:60:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:56:13:56:21 | "session" | session |
| CookieWithoutHttpOnly.go:90:2:90:22 | call to SetCookie | CookieWithoutHttpOnly.go:86:10:86:18 | "session" | CookieWithoutHttpOnly.go:90:20:90:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:86:10:86:18 | "session" | session |
| CookieWithoutHttpOnly.go:109:2:109:22 | call to SetCookie | CookieWithoutHttpOnly.go:103:10:103:18 | "session" | CookieWithoutHttpOnly.go:109:20:109:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:103:10:103:18 | "session" | session |
| CookieWithoutHttpOnly.go:119:2:119:22 | call to SetCookie | CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | CookieWithoutHttpOnly.go:119:20:119:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | login_name |
| CookieWithoutHttpOnly.go:119:2:119:22 | call to SetCookie | CookieWithoutHttpOnly.go:115:10:115:16 | session | CookieWithoutHttpOnly.go:119:20:119:21 | &... | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:115:10:115:16 | session | session |
| CookieWithoutHttpOnly.go:131:4:131:71 | call to SetCookie | CookieWithoutHttpOnly.go:131:16:131:24 | "session" | CookieWithoutHttpOnly.go:131:16:131:24 | "session" | Sensitive cookie $@ does not set HttpOnly attribute to true. | CookieWithoutHttpOnly.go:131:16:131:24 | "session" | session |
edges
| CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | CookieWithoutHttpOnly.go:14:20:14:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | CookieWithoutHttpOnly.go:14:21:14:21 | c | provenance | |
| CookieWithoutHttpOnly.go:11:10:11:18 | "session" | CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:14:20:14:21 | &... [pointer] | CookieWithoutHttpOnly.go:14:20:14:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:14:21:14:21 | c | CookieWithoutHttpOnly.go:14:20:14:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:14:21:14:21 | c | CookieWithoutHttpOnly.go:14:20:14:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | CookieWithoutHttpOnly.go:23:20:23:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | CookieWithoutHttpOnly.go:23:21:23:21 | c | provenance | |
| CookieWithoutHttpOnly.go:19:13:19:21 | "session" | CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... [pointer] | CookieWithoutHttpOnly.go:23:20:23:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:23:21:23:21 | c | CookieWithoutHttpOnly.go:23:20:23:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:23:21:23:21 | c | CookieWithoutHttpOnly.go:23:20:23:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | CookieWithoutHttpOnly.go:32:20:32:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | CookieWithoutHttpOnly.go:32:21:32:21 | c | provenance | |
| CookieWithoutHttpOnly.go:28:13:28:21 | "session" | CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:32:20:32:21 | &... [pointer] | CookieWithoutHttpOnly.go:32:20:32:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:32:21:32:21 | c | CookieWithoutHttpOnly.go:32:20:32:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:32:21:32:21 | c | CookieWithoutHttpOnly.go:32:20:32:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | CookieWithoutHttpOnly.go:41:20:41:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | CookieWithoutHttpOnly.go:41:21:41:21 | c | provenance | |
| CookieWithoutHttpOnly.go:37:10:37:18 | "session" | CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:41:20:41:21 | &... [pointer] | CookieWithoutHttpOnly.go:41:20:41:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:41:21:41:21 | c | CookieWithoutHttpOnly.go:41:20:41:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:41:21:41:21 | c | CookieWithoutHttpOnly.go:41:20:41:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | CookieWithoutHttpOnly.go:50:20:50:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | CookieWithoutHttpOnly.go:50:21:50:21 | c | provenance | |
| CookieWithoutHttpOnly.go:46:10:46:18 | "session" | CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... [pointer] | CookieWithoutHttpOnly.go:50:20:50:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:50:21:50:21 | c | CookieWithoutHttpOnly.go:50:20:50:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:50:21:50:21 | c | CookieWithoutHttpOnly.go:50:20:50:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | CookieWithoutHttpOnly.go:60:20:60:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | CookieWithoutHttpOnly.go:60:21:60:21 | c | provenance | |
| CookieWithoutHttpOnly.go:56:13:56:21 | "session" | CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... [pointer] | CookieWithoutHttpOnly.go:60:20:60:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:60:21:60:21 | c | CookieWithoutHttpOnly.go:60:20:60:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:60:21:60:21 | c | CookieWithoutHttpOnly.go:60:20:60:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | CookieWithoutHttpOnly.go:70:20:70:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | CookieWithoutHttpOnly.go:70:21:70:21 | c | provenance | |
| CookieWithoutHttpOnly.go:66:13:66:21 | "session" | CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:70:20:70:21 | &... [pointer] | CookieWithoutHttpOnly.go:70:20:70:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:70:21:70:21 | c | CookieWithoutHttpOnly.go:70:20:70:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:70:21:70:21 | c | CookieWithoutHttpOnly.go:70:20:70:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | CookieWithoutHttpOnly.go:80:20:80:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | CookieWithoutHttpOnly.go:80:21:80:21 | c | provenance | |
| CookieWithoutHttpOnly.go:76:10:76:18 | "session" | CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:80:20:80:21 | &... [pointer] | CookieWithoutHttpOnly.go:80:20:80:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:80:21:80:21 | c | CookieWithoutHttpOnly.go:80:20:80:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:80:21:80:21 | c | CookieWithoutHttpOnly.go:80:20:80:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | CookieWithoutHttpOnly.go:90:20:90:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | CookieWithoutHttpOnly.go:90:21:90:21 | c | provenance | |
| CookieWithoutHttpOnly.go:86:10:86:18 | "session" | CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... [pointer] | CookieWithoutHttpOnly.go:90:20:90:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:90:21:90:21 | c | CookieWithoutHttpOnly.go:90:20:90:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:90:21:90:21 | c | CookieWithoutHttpOnly.go:90:20:90:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:103:10:103:18 | "session" | CookieWithoutHttpOnly.go:105:10:105:13 | name | provenance | |
| CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | CookieWithoutHttpOnly.go:109:20:109:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | CookieWithoutHttpOnly.go:109:21:109:21 | c | provenance | |
| CookieWithoutHttpOnly.go:105:10:105:13 | name | CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... [pointer] | CookieWithoutHttpOnly.go:109:20:109:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:109:21:109:21 | c | CookieWithoutHttpOnly.go:109:20:109:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:109:21:109:21 | c | CookieWithoutHttpOnly.go:109:20:109:21 | &... [pointer] | provenance | |
| CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | CookieWithoutHttpOnly.go:115:10:115:16 | session | provenance | |
| CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | CookieWithoutHttpOnly.go:119:20:119:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | CookieWithoutHttpOnly.go:119:21:119:21 | c | provenance | |
| CookieWithoutHttpOnly.go:115:10:115:16 | session | CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | provenance | Config |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... [pointer] | CookieWithoutHttpOnly.go:119:20:119:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:119:21:119:21 | c | CookieWithoutHttpOnly.go:119:20:119:21 | &... | provenance | |
| CookieWithoutHttpOnly.go:119:21:119:21 | c | CookieWithoutHttpOnly.go:119:20:119:21 | &... [pointer] | provenance | |
nodes
| CookieWithoutHttpOnly.go:10:7:13:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:11:10:11:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:14:20:14:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:14:20:14:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:14:21:14:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:18:7:22:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:19:13:19:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:23:21:23:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:27:7:31:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:28:13:28:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:32:20:32:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:32:20:32:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:32:21:32:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:36:7:39:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:37:10:37:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:41:20:41:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:41:20:41:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:41:21:41:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:45:7:48:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:46:10:46:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:50:21:50:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:55:7:59:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:56:13:56:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:60:21:60:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:65:7:69:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:66:13:66:21 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:70:20:70:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:70:20:70:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:70:21:70:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:75:7:78:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:76:10:76:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:80:20:80:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:80:20:80:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:80:21:80:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:85:7:88:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:86:10:86:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:90:21:90:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:103:10:103:18 | "session" | semmle.label | "session" |
| CookieWithoutHttpOnly.go:104:7:107:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:105:10:105:13 | name | semmle.label | name |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:109:21:109:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:113:13:113:24 | "login_name" | semmle.label | "login_name" |
| CookieWithoutHttpOnly.go:114:7:117:2 | struct literal | semmle.label | struct literal |
| CookieWithoutHttpOnly.go:115:10:115:16 | session | semmle.label | session |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... | semmle.label | &... |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... [pointer] | semmle.label | &... [pointer] |
| CookieWithoutHttpOnly.go:119:21:119:21 | c | semmle.label | c |
| CookieWithoutHttpOnly.go:131:16:131:24 | "session" | semmle.label | "session" |
subpaths

View File

@@ -0,0 +1,136 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
HttpOnly: false,
}
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = true
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // $ Alert // BAD: HttpOnly explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // $ Alert //BAD: HttpOnly explicitly set to false
}
func handler10(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "consent",
Value: "1",
}
c.HttpOnly = false
http.SetCookie(w, &c) // GOOD: Name is not auth related
}
func handler11(w http.ResponseWriter, r *http.Request) {
name := "session" // $ Source
c := http.Cookie{
Name: name,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // $ Alert // BAD: auth related name
}
func handler12(w http.ResponseWriter, r *http.Request) {
session := "login_name" // $ Source
c := http.Cookie{
Name: session, // $ Source
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // $ Alert // BAD: auth related name
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // $ Alert // BAD: httpOnly set to false
}
})
router.Run()
}

View File

@@ -0,0 +1,2 @@
query: Security/CWE-1004/CookieWithoutHttpOnly.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,5 +4,4 @@ go 1.14
require (
github.com/gin-gonic/gin v1.7.1
github.com/gorilla/sessions v1.2.1
)

View File

@@ -0,0 +1,3 @@
# github.com/gin-gonic/gin v1.7.1
## explicit
github.com/gin-gonic/gin

View File

@@ -0,0 +1,6 @@
| CookieWithoutSecure.go:14:2:14:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:23:2:23:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:50:2:50:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:60:2:60:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:90:2:90:22 | call to SetCookie | Cookie does not set Secure attribute to true. |
| CookieWithoutSecure.go:102:4:102:71 | call to SetCookie | Cookie does not set Secure attribute to true. |

View File

@@ -0,0 +1,107 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
http.SetCookie(w, &c) // $ Alert // BAD: Secure set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
Secure: false,
}
http.SetCookie(w, &c) // $ Alert // BAD: Secure explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
Secure: true,
}
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.Secure = true
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.Secure = false
http.SetCookie(w, &c) // $ Alert // BAD: Secure explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
Secure: val,
}
http.SetCookie(w, &c) // $ Alert // BAD: Secure explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
Secure: val,
}
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.Secure = val
http.SetCookie(w, &c) // GOOD: Secure explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session", // $ Source
Value: "secret",
}
c.Secure = val
http.SetCookie(w, &c) // $ Alert //BAD: Secure explicitly set to false
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // $ Alert // BAD: Secure set to false
}
})
router.Run()
}

View File

@@ -0,0 +1,2 @@
query: Security/CWE-614/CookieWithoutSecure.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,7 @@
module example.com/m
go 1.14
require (
github.com/gin-gonic/gin v1.7.1
)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Manuel Martínez-Almeida
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,12 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gin-gonic/gin/binding, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gin-gonic/gin/binding (exports: ; functions: YAML)
// Package binding is a stub of github.com/gin-gonic/gin/binding, generated by depstubber.
package binding
import ()
var YAML interface{} = nil

View File

@@ -0,0 +1,677 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gin-gonic/gin, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gin-gonic/gin (exports: Context; functions: Default)
// Package gin is a stub of github.com/gin-gonic/gin, generated by depstubber.
package gin
import (
bufio "bufio"
template "html/template"
io "io"
multipart "mime/multipart"
net "net"
http "net/http"
time "time"
)
type Context struct {
Request *http.Request
Writer ResponseWriter
Params Params
Keys map[string]interface{}
Errors interface{}
Accepted []string
}
func (_ *Context) Abort() {}
func (_ *Context) AbortWithError(_ int, _ error) *Error {
return nil
}
func (_ *Context) AbortWithStatus(_ int) {}
func (_ *Context) AbortWithStatusJSON(_ int, _ interface{}) {}
func (_ *Context) AsciiJSON(_ int, _ interface{}) {}
func (_ *Context) Bind(_ interface{}) error {
return nil
}
func (_ *Context) BindHeader(_ interface{}) error {
return nil
}
func (_ *Context) BindJSON(_ interface{}) error {
return nil
}
func (_ *Context) BindQuery(_ interface{}) error {
return nil
}
func (_ *Context) BindUri(_ interface{}) error {
return nil
}
func (_ *Context) BindWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) BindXML(_ interface{}) error {
return nil
}
func (_ *Context) BindYAML(_ interface{}) error {
return nil
}
func (_ *Context) ClientIP() string {
return ""
}
func (_ *Context) ContentType() string {
return ""
}
func (_ *Context) Cookie(_ string) (string, error) {
return "", nil
}
func (_ *Context) Copy() *Context {
return nil
}
func (_ *Context) Data(_ int, _ string, _ []byte) {}
func (_ *Context) DataFromReader(_ int, _ int64, _ string, _ io.Reader, _ map[string]string) {}
func (_ *Context) Deadline() (time.Time, bool) {
return time.Time{}, false
}
func (_ *Context) DefaultPostForm(_ string, _ string) string {
return ""
}
func (_ *Context) DefaultQuery(_ string, _ string) string {
return ""
}
func (_ *Context) Done() <-chan struct{} {
return nil
}
func (_ *Context) Err() error {
return nil
}
func (_ *Context) Error(_ error) *Error {
return nil
}
func (_ *Context) File(_ string) {}
func (_ *Context) FileAttachment(_ string, _ string) {}
func (_ *Context) FileFromFS(_ string, _ http.FileSystem) {}
func (_ *Context) FormFile(_ string) (*multipart.FileHeader, error) {
return nil, nil
}
func (_ *Context) FullPath() string {
return ""
}
func (_ *Context) Get(_ string) (interface{}, bool) {
return nil, false
}
func (_ *Context) GetBool(_ string) bool {
return false
}
func (_ *Context) GetDuration(_ string) time.Duration {
return 0
}
func (_ *Context) GetFloat64(_ string) float64 {
return 0
}
func (_ *Context) GetHeader(_ string) string {
return ""
}
func (_ *Context) GetInt(_ string) int {
return 0
}
func (_ *Context) GetInt64(_ string) int64 {
return 0
}
func (_ *Context) GetPostForm(_ string) (string, bool) {
return "", false
}
func (_ *Context) GetPostFormArray(_ string) ([]string, bool) {
return nil, false
}
func (_ *Context) GetPostFormMap(_ string) (map[string]string, bool) {
return nil, false
}
func (_ *Context) GetQuery(_ string) (string, bool) {
return "", false
}
func (_ *Context) GetQueryArray(_ string) ([]string, bool) {
return nil, false
}
func (_ *Context) GetQueryMap(_ string) (map[string]string, bool) {
return nil, false
}
func (_ *Context) GetRawData() ([]byte, error) {
return nil, nil
}
func (_ *Context) GetString(_ string) string {
return ""
}
func (_ *Context) GetStringMap(_ string) map[string]interface{} {
return nil
}
func (_ *Context) GetStringMapString(_ string) map[string]string {
return nil
}
func (_ *Context) GetStringMapStringSlice(_ string) map[string][]string {
return nil
}
func (_ *Context) GetStringSlice(_ string) []string {
return nil
}
func (_ *Context) GetTime(_ string) time.Time {
return time.Time{}
}
func (_ *Context) GetUint(_ string) uint {
return 0
}
func (_ *Context) GetUint64(_ string) uint64 {
return 0
}
func (_ *Context) HTML(_ int, _ string, _ interface{}) {}
func (_ *Context) Handler() HandlerFunc {
return nil
}
func (_ *Context) HandlerName() string {
return ""
}
func (_ *Context) HandlerNames() []string {
return nil
}
func (_ *Context) Header(_ string, _ string) {}
func (_ *Context) IndentedJSON(_ int, _ interface{}) {}
func (_ *Context) IsAborted() bool {
return false
}
func (_ *Context) IsWebsocket() bool {
return false
}
func (_ *Context) JSON(_ int, _ interface{}) {}
func (_ *Context) JSONP(_ int, _ interface{}) {}
func (_ *Context) MultipartForm() (*multipart.Form, error) {
return nil, nil
}
func (_ *Context) MustBindWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) MustGet(_ string) interface{} {
return nil
}
func (_ *Context) Negotiate(_ int, _ Negotiate) {}
func (_ *Context) NegotiateFormat(_ ...string) string {
return ""
}
func (_ *Context) Next() {}
func (_ *Context) Param(_ string) string {
return ""
}
func (_ *Context) PostForm(_ string) string {
return ""
}
func (_ *Context) PostFormArray(_ string) []string {
return nil
}
func (_ *Context) PostFormMap(_ string) map[string]string {
return nil
}
func (_ *Context) ProtoBuf(_ int, _ interface{}) {}
func (_ *Context) PureJSON(_ int, _ interface{}) {}
func (_ *Context) Query(_ string) string {
return ""
}
func (_ *Context) QueryArray(_ string) []string {
return nil
}
func (_ *Context) QueryMap(_ string) map[string]string {
return nil
}
func (_ *Context) Redirect(_ int, _ string) {}
func (_ *Context) RemoteIP() (net.IP, bool) {
return nil, false
}
func (_ *Context) Render(_ int, _ interface{}) {}
func (_ *Context) SSEvent(_ string, _ interface{}) {}
func (_ *Context) SaveUploadedFile(_ *multipart.FileHeader, _ string) error {
return nil
}
func (_ *Context) SecureJSON(_ int, _ interface{}) {}
func (_ *Context) Set(_ string, _ interface{}) {}
func (_ *Context) SetAccepted(_ ...string) {}
func (_ *Context) SetCookie(_ string, _ string, _ int, _ string, _ string, _ bool, _ bool) {}
func (_ *Context) SetSameSite(_ http.SameSite) {}
func (_ *Context) ShouldBind(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindBodyWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) ShouldBindHeader(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindJSON(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindQuery(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindUri(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindWith(_ interface{}, _ interface{}) error {
return nil
}
func (_ *Context) ShouldBindXML(_ interface{}) error {
return nil
}
func (_ *Context) ShouldBindYAML(_ interface{}) error {
return nil
}
func (_ *Context) Status(_ int) {}
func (_ *Context) Stream(_ func(io.Writer) bool) bool {
return false
}
func (_ *Context) String(_ int, _ string, _ ...interface{}) {}
func (_ *Context) Value(_ interface{}) interface{} {
return nil
}
func (_ *Context) XML(_ int, _ interface{}) {}
func (_ *Context) YAML(_ int, _ interface{}) {}
func Default() *Engine {
return nil
}
type Engine struct {
RouterGroup RouterGroup
RedirectTrailingSlash bool
RedirectFixedPath bool
HandleMethodNotAllowed bool
ForwardedByClientIP bool
RemoteIPHeaders []string
TrustedProxies []string
AppEngine bool
UseRawPath bool
UnescapePathValues bool
MaxMultipartMemory int64
RemoveExtraSlash bool
HTMLRender interface{}
FuncMap template.FuncMap
}
func (_ *Engine) Any(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) BasePath() string {
return ""
}
func (_ *Engine) DELETE(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Delims(_ string, _ string) *Engine {
return nil
}
func (_ *Engine) GET(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Group(_ string, _ ...HandlerFunc) *RouterGroup {
return nil
}
func (_ *Engine) HEAD(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Handle(_ string, _ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) HandleContext(_ *Context) {}
func (_ *Engine) LoadHTMLFiles(_ ...string) {}
func (_ *Engine) LoadHTMLGlob(_ string) {}
func (_ *Engine) NoMethod(_ ...HandlerFunc) {}
func (_ *Engine) NoRoute(_ ...HandlerFunc) {}
func (_ *Engine) OPTIONS(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) PATCH(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) POST(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) PUT(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *Engine) Routes() RoutesInfo {
return nil
}
func (_ *Engine) Run(_ ...string) error {
return nil
}
func (_ *Engine) RunFd(_ int) error {
return nil
}
func (_ *Engine) RunListener(_ net.Listener) error {
return nil
}
func (_ *Engine) RunTLS(_ string, _ string, _ string) error {
return nil
}
func (_ *Engine) RunUnix(_ string) error {
return nil
}
func (_ *Engine) SecureJsonPrefix(_ string) *Engine {
return nil
}
func (_ *Engine) ServeHTTP(_ http.ResponseWriter, _ *http.Request) {}
func (_ *Engine) SetFuncMap(_ template.FuncMap) {}
func (_ *Engine) SetHTMLTemplate(_ *template.Template) {}
func (_ *Engine) Static(_ string, _ string) IRoutes {
return nil
}
func (_ *Engine) StaticFS(_ string, _ http.FileSystem) IRoutes {
return nil
}
func (_ *Engine) StaticFile(_ string, _ string) IRoutes {
return nil
}
func (_ *Engine) Use(_ ...HandlerFunc) IRoutes {
return nil
}
type Error struct {
Err error
Type ErrorType
Meta interface{}
}
func (_ Error) Error() string {
return ""
}
func (_ *Error) IsType(_ ErrorType) bool {
return false
}
func (_ *Error) JSON() interface{} {
return nil
}
func (_ *Error) MarshalJSON() ([]byte, error) {
return nil, nil
}
func (_ *Error) SetMeta(_ interface{}) *Error {
return nil
}
func (_ *Error) SetType(_ ErrorType) *Error {
return nil
}
func (_ *Error) Unwrap() error {
return nil
}
type ErrorType uint64
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
func (_ HandlersChain) Last() HandlerFunc {
return nil
}
type IRoutes interface {
Any(_ string, _ ...HandlerFunc) IRoutes
DELETE(_ string, _ ...HandlerFunc) IRoutes
GET(_ string, _ ...HandlerFunc) IRoutes
HEAD(_ string, _ ...HandlerFunc) IRoutes
Handle(_ string, _ string, _ ...HandlerFunc) IRoutes
OPTIONS(_ string, _ ...HandlerFunc) IRoutes
PATCH(_ string, _ ...HandlerFunc) IRoutes
POST(_ string, _ ...HandlerFunc) IRoutes
PUT(_ string, _ ...HandlerFunc) IRoutes
Static(_ string, _ string) IRoutes
StaticFS(_ string, _ http.FileSystem) IRoutes
StaticFile(_ string, _ string) IRoutes
Use(_ ...HandlerFunc) IRoutes
}
type Negotiate struct {
Offered []string
HTMLName string
HTMLData interface{}
JSONData interface{}
XMLData interface{}
YAMLData interface{}
Data interface{}
}
type Param struct {
Key string
Value string
}
type Params []Param
func (_ Params) ByName(_ string) string {
return ""
}
func (_ Params) Get(_ string) (string, bool) {
return "", false
}
type ResponseWriter interface {
CloseNotify() <-chan bool
Flush()
Header() http.Header
Hijack() (net.Conn, *bufio.ReadWriter, error)
Pusher() http.Pusher
Size() int
Status() int
Write(_ []byte) (int, error)
WriteHeader(_ int)
WriteHeaderNow()
WriteString(_ string) (int, error)
Written() bool
}
type RouteInfo struct {
Method string
Path string
Handler string
HandlerFunc HandlerFunc
}
type RouterGroup struct {
Handlers HandlersChain
}
func (_ *RouterGroup) Any(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) BasePath() string {
return ""
}
func (_ *RouterGroup) DELETE(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) GET(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) Group(_ string, _ ...HandlerFunc) *RouterGroup {
return nil
}
func (_ *RouterGroup) HEAD(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) Handle(_ string, _ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) OPTIONS(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) PATCH(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) POST(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) PUT(_ string, _ ...HandlerFunc) IRoutes {
return nil
}
func (_ *RouterGroup) Static(_ string, _ string) IRoutes {
return nil
}
func (_ *RouterGroup) StaticFS(_ string, _ http.FileSystem) IRoutes {
return nil
}
func (_ *RouterGroup) StaticFile(_ string, _ string) IRoutes {
return nil
}
func (_ *RouterGroup) Use(_ ...HandlerFunc) IRoutes {
return nil
}
type RoutesInfo []RouteInfo

View File

@@ -0,0 +1,3 @@
# github.com/gin-gonic/gin v1.7.1
## explicit
github.com/gin-gonic/gin

View File

@@ -86,6 +86,8 @@ pragma[nomagic]
private predicate constantIntegerExpr(Expr e, int val) {
e.(CompileTimeConstantExpr).getIntValue() = val
or
e.(LongLiteral).getValue().toInt() = val
or
exists(SsaExplicitWrite v, Expr src |
e = v.getARead() and
src = v.getValue() and

View File

@@ -2,7 +2,7 @@ import rust
import codeql.rust.internal.PathResolution
import utils.test.PathResolutionInlineExpectationsTest
query predicate resolveDollarCrate(RelevantPath p, Crate c) {
query predicate resolveDollarCrate(PathExt p, Crate c) {
c = resolvePath(p) and
p.isDollarCrate() and
p.fromSource() and

View File

@@ -11,6 +11,7 @@ ql/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql
ql/rust/ql/src/queries/security/CWE-020/RegexInjection.ql
ql/rust/ql/src/queries/security/CWE-022/TaintedPath.ql
ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
ql/rust/ql/src/queries/security/CWE-295/DisabledCertificateCheck.ql
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql

View File

@@ -12,6 +12,7 @@ ql/rust/ql/src/queries/security/CWE-020/RegexInjection.ql
ql/rust/ql/src/queries/security/CWE-022/TaintedPath.ql
ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
ql/rust/ql/src/queries/security/CWE-117/LogInjection.ql
ql/rust/ql/src/queries/security/CWE-295/DisabledCertificateCheck.ql
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql

View File

@@ -12,6 +12,7 @@ ql/rust/ql/src/queries/security/CWE-020/RegexInjection.ql
ql/rust/ql/src/queries/security/CWE-022/TaintedPath.ql
ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
ql/rust/ql/src/queries/security/CWE-117/LogInjection.ql
ql/rust/ql/src/queries/security/CWE-295/DisabledCertificateCheck.ql
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added more detailed models for `std::fs` and `std::path`.

View File

@@ -1,5 +1,6 @@
private import codeql.util.Boolean
private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl
private import rust
newtype TCompletion =
@@ -123,13 +124,7 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
*/
private predicate cannotCauseMatchFailure(Pat pat) {
pat instanceof RangePat or
// Identifier patterns that are in fact path patterns can cause failures. For
// instance `None`. Only if an `@ ...` part is present can we be sure that
// it's an actual identifier pattern. As a heuristic, if the identifier starts
// with a lower case letter, then we assume that it's an identifier. This
// works for code that follows the Rust naming convention for enums and
// constants.
pat = any(IdentPat p | p.hasPat() or p.getName().getText().charAt(0).isLowercase()) or
pat = any(IdentPat p | p.hasPat() or VariableImpl::variableDecl(_, p.getName(), _)) or
pat instanceof WildcardPat or
pat instanceof RestPat or
pat instanceof RefPat or

View File

@@ -82,7 +82,7 @@ module Impl {
}
private predicate callHasTraitQualifier(CallExpr call, Trait qualifier) {
exists(RelevantPath qualifierPath |
exists(PathExt qualifierPath |
callHasQualifier(call, _, qualifierPath) and
qualifier = resolvePath(qualifierPath) and
// When the qualifier is `Self` and resolves to a trait, it's inside a

View File

@@ -5,6 +5,8 @@
*/
private import codeql.rust.elements.internal.generated.Const
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
private import codeql.rust.elements.internal.IdentPatImpl::Impl as IdentPatImpl
private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl
private import codeql.rust.internal.PathResolution
@@ -36,14 +38,30 @@ module Impl {
* }
* ```
*/
class ConstAccess extends PathExprImpl::PathExpr {
private Const c;
ConstAccess() { c = resolvePath(this.getPath()) }
abstract class ConstAccess extends AstNodeImpl::AstNode {
/** Gets the constant being accessed. */
Const getConst() { result = c }
abstract Const getConst();
override string getAPrimaryQlClass() { result = "ConstAccess" }
}
private class PathExprConstAccess extends ConstAccess, PathExprImpl::PathExpr {
private Const c;
PathExprConstAccess() { c = resolvePath(this.getPath()) }
override Const getConst() { result = c }
override string getAPrimaryQlClass() { result = ConstAccess.super.getAPrimaryQlClass() }
}
private class IdentPatConstAccess extends ConstAccess, IdentPatImpl::IdentPat {
private Const c;
IdentPatConstAccess() { c = resolvePath(this) }
override Const getConst() { result = c }
override string getAPrimaryQlClass() { result = ConstAccess.super.getAPrimaryQlClass() }
}
}

View File

@@ -31,6 +31,8 @@ module Impl {
override string toStringImpl() { result = this.getName() }
override string getAPrimaryQlClass() { result = "FormatTemplateVariableAccess" }
/** Gets the name of the variable */
string getName() { result = argument.getName() }

View File

@@ -4,6 +4,7 @@
* INTERNAL: Do not use.
*/
private import rust
private import codeql.rust.elements.internal.generated.PathExpr
/**
@@ -25,5 +26,11 @@ module Impl {
override string toStringImpl() { result = this.toAbbreviatedString() }
override string toAbbreviatedString() { result = this.getPath().toStringImpl() }
override string getAPrimaryQlClass() {
if this instanceof VariableAccess
then result = "VariableAccess"
else result = super.getAPrimaryQlClass()
}
}
}

View File

@@ -1,8 +1,9 @@
private import rust
private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.internal.PathResolution as PathResolution
private import codeql.rust.elements.internal.generated.ParentChild as ParentChild
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl
private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl::Impl as FormatTemplateVariableAccessImpl
private import codeql.util.DenseRank
@@ -98,7 +99,7 @@ module Impl {
* pattern.
*/
cached
private predicate variableDecl(AstNode definingNode, Name name, string text) {
predicate variableDecl(AstNode definingNode, Name name, string text) {
Cached::ref() and
exists(SelfParam sp |
name = sp.getName() and
@@ -117,11 +118,7 @@ module Impl {
not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name
) and
text = name.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 text.charAt(0).isUppercase() and
not PathResolution::identPatIsResolvable(pat) 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.getAParam().getPat() = pat) and
@@ -666,7 +663,7 @@ module Impl {
}
/** A variable access. */
class VariableAccess extends PathExprBaseImpl::PathExprBase {
class VariableAccess extends PathExprBase {
private string name;
private Variable v;
@@ -677,10 +674,6 @@ module Impl {
/** Holds if this access is a capture. */
predicate isCapture() { this.getEnclosingCfgScope() != v.getEnclosingCfgScope() }
override string toStringImpl() { result = name }
override string getAPrimaryQlClass() { result = "VariableAccess" }
}
/** Holds if `e` occurs in the LHS of an assignment or compound assignment. */
@@ -722,7 +715,7 @@ module Impl {
}
/** A nested function access. */
class NestedFunctionAccess extends PathExprBaseImpl::PathExprBase {
class NestedFunctionAccess extends PathExprBase {
private Function f;
NestedFunctionAccess() { nestedFunctionAccess(_, f, this) }

View File

@@ -0,0 +1,9 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
- ["<native_tls::TlsConnectorBuilder>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
- ["<native_tls::TlsConnectorBuilder>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
- ["<async_native_tls::connect::TlsConnector>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
- ["<async_native_tls::connect::TlsConnector>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]

View File

@@ -11,6 +11,10 @@ extensions:
data:
- ["<reqwest::async_impl::client::Client>::request", "Argument[1]", "request-url", "manual"]
- ["<reqwest::blocking::client::Client>::request", "Argument[1]", "request-url", "manual"]
- ["<reqwest::async_impl::client::ClientBuilder>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
- ["<reqwest::async_impl::client::ClientBuilder>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
- ["<reqwest::blocking::client::ClientBuilder>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
- ["<reqwest::blocking::client::ClientBuilder>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: summaryModel

View File

@@ -60,6 +60,7 @@ extensions:
- ["core::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"]
- ["core::ptr::dangling_mut", "ReturnValue", "pointer-invalidate", "manual"]
- ["core::ptr::null", "ReturnValue", "pointer-invalidate", "manual"]
- ["core::ptr::null_mut", "ReturnValue", "pointer-invalidate", "manual"]
- ["v8::primitives::null", "ReturnValue", "pointer-invalidate", "manual"]
- addsTo:
pack: codeql/rust-all

View File

@@ -3,14 +3,27 @@ extensions:
pack: codeql/rust-all
extensible: sourceModel
data:
- ["std::fs::exists", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["std::fs::read", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["std::fs::read_dir", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["std::fs::read_to_string", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["std::fs::read_link", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["std::fs::metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["std::fs::symlink_metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::fs::DirEntry>::path", "ReturnValue", "file", "manual"]
- ["<std::fs::DirEntry>::file_name", "ReturnValue", "file", "manual"]
- ["<std::fs::File>::open", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::fs::File>::open_buffered", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::fs::OpenOptions>::open", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::path::Path>::exists", "ReturnValue", "file", "manual"]
- ["<std::path::Path>::try_exists", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::path::Path>::is_file", "ReturnValue", "file", "manual"]
- ["<std::path::Path>::is_dir", "ReturnValue", "file", "manual"]
- ["<std::path::Path>::is_symlink", "ReturnValue", "file", "manual"]
- ["<std::path::Path>::metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::path::Path>::symlink_metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::path::Path>::read_dir", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- ["<std::path::Path>::read_link", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
@@ -68,3 +81,12 @@ extensions:
- ["<std::path::Path>::with_extension", "Argument[Self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::path::Path>::with_file_name", "Argument[Self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::path::Path>::with_file_name", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["<std::fs::Metadata>::accessed", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
- ["<std::fs::Metadata>::created", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
- ["<std::fs::Metadata>::file_type", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::fs::Metadata>::is_file", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::fs::Metadata>::is_dir", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::fs::Metadata>::is_symlink", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::fs::Metadata>::len", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
- ["<std::fs::Metadata>::modified", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
- ["<std::fs::Metadata>::permissions", "Argument[self].Reference", "ReturnValue", "taint", "manual"]

View File

@@ -115,13 +115,11 @@ module Stages {
predicate backref() {
1 = 1
or
exists(resolvePath(_))
exists(resolvePathIgnoreVariableShadowing(_))
or
exists(any(ItemNode i).getASuccessor(_, _, _))
or
exists(any(ImplOrTraitItemNode i).getASelfPath())
or
any(TypeParamItemNode i).hasTraitBound()
}
}

View File

@@ -37,6 +37,9 @@ private module Cached {
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } or
TItemNode(ItemNode i)
pragma[nomagic]
private predicate isMacroCallLocation(Location loc) { loc = any(MacroCall m).getLocation() }
/**
* Gets an element, of kind `kind`, that element `use` uses, if any.
*/
@@ -44,7 +47,7 @@ private module Cached {
Definition definitionOf(Use use, string kind) {
result = use.getDefinition() and
kind = use.getUseType() and
not result.getLocation() = any(MacroCall m).getLocation()
not isMacroCallLocation(result.getLocation())
}
}

View File

@@ -1,9 +1,49 @@
/**
* Provides functionality for resolving paths, using the predicate `resolvePath`.
*
* Path resolution needs to happen before variable resolution, because otherwise
* we cannot know whether an identifier pattern binds a new variable or whether it
* refers to a constructor or constant:
*
* ```rust
* let x = ...; // `x` is only a variable if it does not resolve to a constructor/constant
* ```
*
* Even though variable names typically start with a lowercase letter and constructors
* with an uppercase letter, this is not enforced by the Rust language.
*
* Variables may shadow declarations, so variable resolution also needs to affect
* path resolution:
*
* ```rust
* fn foo() {} // (1)
*
* fn bar() {
* let f = foo; // `foo` here refers to (1) via path resolution
* let foo = f(); // (2)
* foo // `foo` here refers to (2) via variable resolution
* }
* ```
*
* So it may seem that path resolution and variable resolution must happen in mutual
* recursion, but we would like to keep the inherently global path resolution logic
* separate from the inherently local variable resolution logic. We achieve this by
*
* - First computing global path resolution, where variable shadowing is ignored,
* exposed as the internal predicate `resolvePathIgnoreVariableShadowing`.
* - `resolvePathIgnoreVariableShadowing` is sufficient to determine whether an
* identifier pattern resolves to a constructor/constant, since if it does, it cannot
* be shadowed by a variable. We expose this as the predicate `identPatIsResolvable`.
* - Variable resolution can then be computed as a local property, using only the
* global information from `identPatIsResolvable`.
* - Finally, path resolution can be computed by restricting
* `resolvePathIgnoreVariableShadowing` to paths that are not resolvable via
* variable resolution.
*/
private import rust
private import codeql.rust.elements.internal.generated.ParentChild
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
private import codeql.rust.internal.CachedStages
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
@@ -184,7 +224,7 @@ abstract class ItemNode extends Locatable {
pragma[nomagic]
final Attr getAttr(string name) {
result = this.getAnAttr() and
result.getMeta().getPath().(RelevantPath).isUnqualified(name)
result.getMeta().getPath().(PathExt).isUnqualified(name)
}
final predicate hasAttr(string name) { exists(this.getAttr(name)) }
@@ -1159,34 +1199,6 @@ final class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
/**
* Holds if this type parameter has a trait bound. Examples:
*
* ```rust
* impl<T> Foo<T> { ... } // has no trait bound
*
* impl<T: Trait> Foo<T> { ... } // has trait bound
*
* impl<T> Foo<T> where T: Trait { ... } // has trait bound
* ```
*/
cached
predicate hasTraitBound() { Stages::PathResolutionStage::ref() and exists(this.getABoundPath()) }
/**
* Holds if this type parameter has no trait bound. Examples:
*
* ```rust
* impl<T> Foo<T> { ... } // has no trait bound
*
* impl<T: Trait> Foo<T> { ... } // has trait bound
*
* impl<T> Foo<T> where T: Trait { ... } // has trait bound
* ```
*/
pragma[nomagic]
predicate hasNoTraitBound() { not this.hasTraitBound() }
override string getName() { result = TypeParam.super.getName().getText() }
override Namespace getNamespace() { result.isType() }
@@ -1525,20 +1537,22 @@ private predicate declares(ItemNode item, Namespace ns, string name) {
)
}
/** A path that does not access a local variable. */
class RelevantPath extends Path {
RelevantPath() { not this = any(VariableAccess va).(PathExpr).getPath() }
/**
* A `Path` or an `IdentPat`.
*
* `IdentPat`s are included in order to resolve unqualified references to
* constructors in patterns.
*/
abstract class PathExt extends AstNode {
abstract string getText();
/** Holds if this is an unqualified path with the textual value `name`. */
pragma[nomagic]
predicate isUnqualified(string name) {
not exists(this.getQualifier()) and
not exists(UseTree tree |
tree.hasPath() and
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
) and
name = this.getText()
}
abstract predicate isUnqualified(string name);
abstract Path getQualifier();
abstract string toStringDebug();
/**
* Holds if this is an unqualified path with the textual value `name` and
@@ -1560,6 +1574,33 @@ class RelevantPath extends Path {
predicate isDollarCrate() { this.isUnqualified("$crate", _) }
}
private class PathExtPath extends PathExt instanceof Path {
override string getText() { result = Path.super.getText() }
override predicate isUnqualified(string name) {
not exists(Path.super.getQualifier()) and
not exists(UseTree tree |
tree.hasPath() and
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
) and
name = Path.super.getText()
}
override Path getQualifier() { result = Path.super.getQualifier() }
override string toStringDebug() { result = Path.super.toStringDebug() }
}
private class PathExtIdentPat extends PathExt, IdentPat {
override string getText() { result = this.getName().getText() }
override predicate isUnqualified(string name) { name = this.getText() }
override Path getQualifier() { none() }
override string toStringDebug() { result = this.getText() }
}
private predicate isModule(ItemNode m) { m instanceof Module }
/** Holds if source file `source` contains the module `m`. */
@@ -1583,7 +1624,7 @@ private ItemNode getOuterScope(ItemNode i) {
pragma[nomagic]
private predicate unqualifiedPathLookup(ItemNode ancestor, string name, Namespace ns, ItemNode encl) {
// lookup in the immediately enclosing item
exists(RelevantPath path |
exists(PathExt path |
path.isUnqualified(name, encl) and
ancestor = encl and
not name = ["crate", "$crate", "super", "self"]
@@ -1619,7 +1660,7 @@ private ItemNode getASuccessor(
private predicate isSourceFile(ItemNode source) { source instanceof SourceFileItemNode }
private predicate hasCratePath(ItemNode i) { any(RelevantPath path).isCratePath(_, i) }
private predicate hasCratePath(ItemNode i) { any(PathExt path).isCratePath(_, i) }
private predicate hasChild(ItemNode parent, ItemNode child) { child.getImmediateParent() = parent }
@@ -1631,7 +1672,7 @@ private predicate sourceFileHasCratePathTc(ItemNode i1, ItemNode i2) =
* `name` may be looked up inside `ancestor`.
*/
pragma[nomagic]
private predicate keywordLookup(ItemNode ancestor, string name, RelevantPath p) {
private predicate keywordLookup(ItemNode ancestor, string name, PathExt p) {
// For `crate`, jump directly to the root module
exists(ItemNode i | p.isCratePath(name, i) |
ancestor instanceof SourceFile and
@@ -1645,7 +1686,7 @@ private predicate keywordLookup(ItemNode ancestor, string name, RelevantPath p)
}
pragma[nomagic]
private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKind kind) {
private ItemNode unqualifiedPathLookup(PathExt p, Namespace ns, SuccessorKind kind) {
exists(ItemNode ancestor, string name |
result = getASuccessor(ancestor, pragma[only_bind_into](name), ns, kind, _) and
kind.isInternalOrBoth()
@@ -1660,7 +1701,7 @@ private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKi
}
pragma[nomagic]
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
private predicate isUnqualifiedSelfPath(PathExt path) { path.isUnqualified("Self") }
/** Provides the input to `TraitIsVisible`. */
signature predicate relevantTraitVisibleSig(Element element, Trait trait);
@@ -1743,14 +1784,14 @@ private module DollarCrateResolution {
isDollarCrateSupportedMacroExpansion(_, expansion)
}
private predicate isDollarCratePath(RelevantPath p) { p.isDollarCrate() }
private predicate isDollarCratePath(PathExt p) { p.isDollarCrate() }
private predicate isInDollarCrateMacroExpansion(RelevantPath p, AstNode expansion) =
private predicate isInDollarCrateMacroExpansion(PathExt p, AstNode expansion) =
doublyBoundedFastTC(hasParent/2, isDollarCratePath/1, isDollarCrateSupportedMacroExpansion/1)(p,
expansion)
pragma[nomagic]
private predicate isInDollarCrateMacroExpansionFromFile(File macroDefFile, RelevantPath p) {
private predicate isInDollarCrateMacroExpansionFromFile(File macroDefFile, PathExt p) {
exists(Path macroDefPath, AstNode expansion |
isDollarCrateSupportedMacroExpansion(macroDefPath, expansion) and
isInDollarCrateMacroExpansion(p, expansion) and
@@ -1765,17 +1806,17 @@ private module DollarCrateResolution {
* calls.
*/
pragma[nomagic]
predicate resolveDollarCrate(RelevantPath p, CrateItemNode crate) {
predicate resolveDollarCrate(PathExt p, CrateItemNode crate) {
isInDollarCrateMacroExpansionFromFile(crate.getASourceFile().getFile(), p)
}
}
pragma[nomagic]
private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
private ItemNode resolvePathCand0(PathExt path, Namespace ns) {
exists(ItemNode res |
res = unqualifiedPathLookup(path, ns, _) and
if
not any(RelevantPath parent).getQualifier() = path and
not any(PathExt parent).getQualifier() = path and
isUnqualifiedSelfPath(path) and
res instanceof ImplItemNode
then result = res.(ImplItemNodeImpl).resolveSelfTyCand()
@@ -1790,13 +1831,16 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
result = resolveUseTreeListItem(_, _, path, _) and
ns = result.getNamespace()
or
result = resolveBuiltin(path.getSegment().getTypeRepr()) and
not path.getSegment().hasTraitTypeRepr() and
ns.isType()
exists(PathSegment seg |
seg = path.(Path).getSegment() and
result = resolveBuiltin(seg.getTypeRepr()) and
not seg.hasTraitTypeRepr() and
ns.isType()
)
}
pragma[nomagic]
private ItemNode resolvePathCandQualifier(RelevantPath qualifier, RelevantPath path, string name) {
private ItemNode resolvePathCandQualifier(PathExt qualifier, PathExt path, string name) {
qualifier = path.getQualifier() and
result = resolvePathCand(qualifier) and
name = path.getText()
@@ -1844,9 +1888,7 @@ private predicate checkQualifiedVisibility(
* qualifier of `path` and `qualifier` resolves to `q`, if any.
*/
pragma[nomagic]
private ItemNode resolvePathCandQualified(
RelevantPath qualifier, ItemNode q, RelevantPath path, Namespace ns
) {
private ItemNode resolvePathCandQualified(PathExt qualifier, ItemNode q, PathExt path, Namespace ns) {
exists(string name, SuccessorKind kind, UseOption useOpt |
q = resolvePathCandQualifier(qualifier, path, name) and
result = getASuccessor(q, name, ns, kind, useOpt) and
@@ -1855,12 +1897,14 @@ private ItemNode resolvePathCandQualified(
}
/** Holds if path `p` must be looked up in namespace `n`. */
private predicate pathUsesNamespace(Path p, Namespace n) {
private predicate pathUsesNamespace(PathExt p, Namespace n) {
n.isValue() and
(
p = any(PathExpr pe).getPath()
or
p = any(TupleStructPat tsp).getPath()
or
p instanceof PathExtIdentPat
)
or
n.isType() and
@@ -1936,7 +1980,7 @@ private predicate macroUseEdge(
* result in non-monotonic recursion.
*/
pragma[nomagic]
private ItemNode resolvePathCand(RelevantPath path) {
private ItemNode resolvePathCand(PathExt path) {
exists(Namespace ns |
result = resolvePathCand0(path, ns) and
if path = any(ImplItemNode i).getSelfPath()
@@ -1949,7 +1993,13 @@ private ItemNode resolvePathCand(RelevantPath path) {
else
if path = any(PathTypeRepr p).getPath()
then result instanceof TypeItemNode
else any()
else
if path instanceof IdentPat
then
result instanceof VariantItemNode or
result instanceof StructItemNode or
result instanceof ConstItemNode
else any()
|
pathUsesNamespace(path, ns)
or
@@ -1966,7 +2016,7 @@ private ItemNode resolvePathCand(RelevantPath path) {
}
/** Get a trait that should be visible when `path` resolves to `node`, if any. */
private Trait getResolvePathTraitUsed(RelevantPath path, AssocItemNode node) {
private Trait getResolvePathTraitUsed(PathExt path, AssocItemNode node) {
exists(TypeItemNode type, ImplItemNodeImpl impl |
node = resolvePathCandQualified(_, type, path, _) and
typeImplEdge(type, impl, _, _, node, _) and
@@ -1978,9 +2028,9 @@ private predicate pathTraitUsed(Element path, Trait trait) {
trait = getResolvePathTraitUsed(path, _)
}
/** Gets the item that `path` resolves to, if any. */
/** INTERNAL: Do not use; use `resolvePath` instead. */
cached
ItemNode resolvePath(RelevantPath path) {
ItemNode resolvePathIgnoreVariableShadowing(PathExt path) {
result = resolvePathCand(path) and
not path = any(Path parent | exists(resolvePathCand(parent))).getQualifier() and
(
@@ -1993,29 +2043,43 @@ ItemNode resolvePath(RelevantPath path) {
or
// if `path` is the qualifier of a resolvable `parent`, then we should
// resolve `path` to something consistent with what `parent` resolves to
exists(RelevantPath parent |
resolvePathCandQualified(path, result, parent, _) = resolvePath(parent)
exists(PathExt parent |
resolvePathCandQualified(path, result, parent, _) = resolvePathIgnoreVariableShadowing(parent)
)
}
private predicate isUseTreeSubPath(UseTree tree, RelevantPath path) {
/**
* Holds if `ip` resolves to some constructor or constant.
*/
// use `forceLocal` once we implement overlay support
pragma[nomagic]
predicate identPatIsResolvable(IdentPat ip) { exists(resolvePathIgnoreVariableShadowing(ip)) }
/** Gets the item that `path` resolves to, if any. */
pragma[nomagic]
ItemNode resolvePath(PathExt path) {
result = resolvePathIgnoreVariableShadowing(path) and
not path = any(VariableAccess va).(PathExpr).getPath()
}
private predicate isUseTreeSubPath(UseTree tree, PathExt path) {
path = tree.getPath()
or
exists(RelevantPath mid |
exists(PathExt mid |
isUseTreeSubPath(tree, mid) and
path = mid.getQualifier()
)
}
pragma[nomagic]
private predicate isUseTreeSubPathUnqualified(UseTree tree, RelevantPath path, string name) {
private predicate isUseTreeSubPathUnqualified(UseTree tree, PathExt path, string name) {
isUseTreeSubPath(tree, path) and
not exists(path.getQualifier()) and
name = path.getText()
}
pragma[nomagic]
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, PathExt path, SuccessorKind kind) {
exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) |
exists(UseTree midTree, ItemNode mid, string name |
mid = resolveUseTreeListItem(use, midTree) and
@@ -2032,9 +2096,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
}
pragma[nomagic]
private ItemNode resolveUseTreeListItemQualifier(
Use use, UseTree tree, RelevantPath path, string name
) {
private ItemNode resolveUseTreeListItemQualifier(Use use, UseTree tree, PathExt path, string name) {
result = resolveUseTreeListItem(use, tree, path.getQualifier(), _) and
name = path.getText()
}
@@ -2189,7 +2251,7 @@ private module Debug {
}
predicate debugUnqualifiedPathLookup(
RelevantPath p, string name, Namespace ns, ItemNode ancestor, string path
PathExt p, string name, Namespace ns, ItemNode ancestor, string path
) {
p = getRelevantLocatable() and
exists(ItemNode encl |
@@ -2199,14 +2261,19 @@ private module Debug {
path = p.toStringDebug()
}
ItemNode debugUnqualifiedPathLookup(PathExt p, Namespace ns, SuccessorKind kind) {
p = getRelevantLocatable() and
result = unqualifiedPathLookup(p, ns, kind)
}
predicate debugItemNode(ItemNode item) { item = getRelevantLocatable() }
ItemNode debugResolvePath(RelevantPath path) {
ItemNode debugResolvePath(PathExt path) {
path = getRelevantLocatable() and
result = resolvePath(path)
}
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, PathExt path, SuccessorKind kind) {
use = getRelevantLocatable() and
result = resolveUseTreeListItem(use, tree, path, kind)
}

View File

@@ -352,7 +352,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
rnk = 0
or
argsAreInstantiationsOfFromIndex(call, abs, f, rnk - 1)
argsAreInstantiationsOfToIndex(call, abs, f, rnk - 1)
)
}
@@ -361,15 +361,15 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
}
}
private module ArgIsInstantiationOfFromIndex =
private module ArgIsInstantiationOfToIndex =
ArgIsInstantiationOf<CallAndPos, ArgIsInstantiationOfInput>;
pragma[nomagic]
private predicate argsAreInstantiationsOfFromIndex(
private predicate argsAreInstantiationsOfToIndex(
Input::Call call, ImplOrTraitItemNode i, Function f, int rnk
) {
exists(FunctionPosition pos |
ArgIsInstantiationOfFromIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
call.hasTargetCand(i, f) and
toCheckRanked(i, f, pos, rnk)
)
@@ -382,7 +382,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
pragma[nomagic]
predicate argsAreInstantiationsOf(Input::Call call, ImplOrTraitItemNode i, Function f) {
exists(int rnk |
argsAreInstantiationsOfFromIndex(call, i, f, rnk) and
argsAreInstantiationsOfToIndex(call, i, f, rnk) and
rnk = max(int r | toCheckRanked(i, f, _, r))
)
}

View File

@@ -9,6 +9,7 @@ private import codeql.rust.dataflow.FlowSource
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.Concepts
private import codeql.rust.dataflow.internal.Node
private import codeql.rust.security.Barriers as Barriers
/**
* Provides default sources, sinks and barriers for detecting accesses to
@@ -59,4 +60,10 @@ module AccessInvalidPointer {
private class ModelsAsDataSink extends Sink {
ModelsAsDataSink() { sinkNode(this, "pointer-access") }
}
/**
* A barrier for invalid pointer access vulnerabilities for values checked to
* be non-`null`.
*/
private class NotNullCheckBarrier extends Barrier instanceof Barriers::NotNullCheckBarrier { }
}

View File

@@ -7,6 +7,8 @@ import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.internal.TypeInference as TypeInference
private import codeql.rust.internal.Type
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
private import codeql.rust.controlflow.CfgNodes as CfgNodes
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
/**
@@ -40,3 +42,25 @@ class IntegralOrBooleanTypeBarrier extends DataFlow::Node {
)
}
}
/**
* Holds if guard expression `g` having result `branch` indicates that the
* sub-expression `e` is not null. For example when `ptr.is_null()` is
* `false`, we have that `ptr` is not null.
*/
private predicate notNullCheck(AstNode g, Expr e, boolean branch) {
exists(MethodCallExpr call |
call.getStaticTarget().getName().getText() = "is_null" and
g = call and
e = call.getReceiver() and
branch = false
)
}
/**
* A node representing a value checked to be non-null. This may be an
* appropriate taint flow barrier for some queries.
*/
class NotNullCheckBarrier extends DataFlow::Node {
NotNullCheckBarrier() { this = DataFlow::BarrierGuard<notNullCheck/3>::getABarrierNode() }
}

View File

@@ -0,0 +1,45 @@
/**
* Provides classes and predicates for reasoning about disabled certificate
* check vulnerabilities.
*/
import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.Concepts
private import codeql.rust.dataflow.internal.Node as Node
/**
* Provides default sinks for detecting disabled certificate check
* vulnerabilities, as well as extension points for adding your own.
*/
module DisabledCertificateCheckExtensions {
/**
* A data flow sink for disabled certificate check vulnerabilities.
*/
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "DisabledCertificateCheck" }
}
/**
* A sink for disabled certificate check vulnerabilities from model data.
*/
private class ModelsAsDataSink extends Sink {
ModelsAsDataSink() { sinkNode(this, "disable-certificate") }
}
/**
* A heuristic sink for disabled certificate check vulnerabilities based on function names.
*/
private class HeuristicSink extends Sink {
HeuristicSink() {
exists(CallExprBase fc |
fc.getStaticTarget().(Function).getName().getText() =
["danger_accept_invalid_certs", "danger_accept_invalid_hostnames"] and
fc.getArg(0) = this.asExpr() and
// don't duplicate modeled sinks
not exists(ModelsAsDataSink s | s.(Node::FlowSummaryNode).getSinkElement().getCall() = fc)
)
}
}
}

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query `rust/disabled-certificate-check`, to detect disabled TLS certificate checks.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `rust/access-invalid-pointer` query has been improved with new flow sources and barriers.

View File

@@ -0,0 +1,42 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
The <code>danger_accept_invalid_certs</code> option on TLS connectors and HTTP clients controls whether certificate verification is performed. If this option is set to <code>true</code>, the client will accept any certificate, making it susceptible to man-in-the-middle attacks.
</p>
<p>
Similarly, the <code>danger_accept_invalid_hostnames</code> option controls whether hostname verification is performed. If this option is set to <code>true</code>, the client will accept any valid certificate regardless of the site that certificate is for, again making it susceptible to man-in-the-middle attacks.
</p>
</overview>
<recommendation>
<p>
Do not set <code>danger_accept_invalid_certs</code> or <code>danger_accept_invalid_hostnames</code> to <code>true</code>, except in controlled environments such as tests. In production, always ensure certificate and hostname verification is enabled to prevent security risks.
</p>
</recommendation>
<example>
<p>
The following code snippet shows a function that creates an HTTP client with certificate verification disabled:
</p>
<sample src="DisabledCertificateCheckBad.rs"/>
<p>
In production code, always configure clients to verify certificates:
</p>
<sample src="DisabledCertificateCheckGood.rs"/>
</example>
<references>
<li>
Rust native-tls crate: <a href="https://docs.rs/native-tls/latest/native_tls/struct.TlsConnectorBuilder.html">TlsConnectorBuilder</a>.
</li>
<li>
Rust reqwest crate: <a href="https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html">ClientBuilder</a>.
</li>
<li>
SSL.com: <a href="https://www.ssl.com/article/browsers-and-certificate-validation/">Browsers and Certificate Validation</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,47 @@
/**
* @name Disabled TLS certificate check
* @description An application that disables TLS certificate checking is more vulnerable to
* man-in-the-middle attacks.
* @kind path-problem
* @problem.severity warning
* @security-severity 7.5
* @precision high
* @id rust/disabled-certificate-check
* @tags security
* external/cwe/cwe-295
*/
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
import codeql.rust.security.DisabledCertificateCheckExtensions
import codeql.rust.Concepts
/**
* A taint configuration for disabled TLS certificate checks.
*/
module DisabledCertificateCheckConfig implements DataFlow::ConfigSig {
import DisabledCertificateCheckExtensions
predicate isSource(DataFlow::Node node) {
// the constant `true`
node.asExpr().(BooleanLiteralExpr).getTextValue() = "true"
or
// a value controlled by a potential attacker
node instanceof ActiveThreatModelSource
}
predicate isSink(DataFlow::Node node) { node instanceof Sink }
predicate observeDiffInformedIncrementalMode() { any() }
}
module DisabledCertificateCheckFlow = TaintTracking::Global<DisabledCertificateCheckConfig>;
import DisabledCertificateCheckFlow::PathGraph
from
DisabledCertificateCheckFlow::PathNode sourceNode, DisabledCertificateCheckFlow::PathNode sinkNode
where DisabledCertificateCheckFlow::flowPath(sourceNode, sinkNode)
select sinkNode.getNode(), sourceNode, sinkNode,
"Disabling TLS certificate validation can expose the application to man-in-the-middle attacks."

View File

@@ -0,0 +1,6 @@
// BAD: Disabling certificate validation in Rust
let _client = reqwest::Client::builder()
.danger_accept_invalid_certs(true) // disables certificate validation
.build()
.unwrap();

View File

@@ -0,0 +1,10 @@
// GOOD: Certificate validation is enabled (default)
let _client = reqwest::Client::builder()
.danger_accept_invalid_certs(false) // certificate validation enabled explicitly
.build()
.unwrap();
let _client = native_tls::TlsConnector::builder() // certificate validation enabled by default
.build()
.unwrap();

View File

@@ -22,11 +22,13 @@ import AccessInvalidPointerFlow::PathGraph
* A data flow configuration for accesses to invalid pointers.
*/
module AccessInvalidPointerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof AccessInvalidPointer::Source }
import AccessInvalidPointer
predicate isSink(DataFlow::Node node) { node instanceof AccessInvalidPointer::Sink }
predicate isSource(DataFlow::Node node) { node instanceof Source }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessInvalidPointer::Barrier }
predicate isSink(DataFlow::Node node) { node instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
predicate isBarrierOut(DataFlow::Node node) {
// make sinks barriers so that we only report the closest instance

View File

@@ -22,6 +22,7 @@ private import codeql.rust.security.AccessInvalidPointerExtensions
private import codeql.rust.security.CleartextLoggingExtensions
private import codeql.rust.security.CleartextStorageDatabaseExtensions
private import codeql.rust.security.CleartextTransmissionExtensions
private import codeql.rust.security.DisabledCertificateCheckExtensions
private import codeql.rust.security.HardcodedCryptographicValueExtensions
private import codeql.rust.security.InsecureCookieExtensions
private import codeql.rust.security.LogInjectionExtensions

View File

@@ -660,7 +660,7 @@ macro_expansion.rs:
# 71| getSegment(): [PathSegment] i32
# 71| getIdentifier(): [NameRef] i32
# 72| getTailExpr(): [CastExpr] a as ...
# 72| getExpr(): [PathExpr,VariableAccess] a
# 72| getExpr(): [VariableAccess] a
# 72| getPath(): [Path] a
# 72| getSegment(): [PathSegment] a
# 72| getIdentifier(): [NameRef] a
@@ -738,7 +738,7 @@ macro_expansion.rs:
# 84| getFunctionBody(): [BlockExpr] { ... }
# 84| getStmtList(): [StmtList] StmtList
# 84| getTailExpr(): [MatchExpr] match self { ... }
# 83| getScrutinee(): [PathExpr,VariableAccess] self
# 83| getScrutinee(): [VariableAccess] self
# 83| getPath(): [Path] self
# 83| getSegment(): [PathSegment] self
# 83| getIdentifier(): [NameRef] self
@@ -751,7 +751,7 @@ macro_expansion.rs:
# 85| getArgList(): [ArgList] ArgList
# 83| getArg(0): [StringLiteralExpr] "field"
# 85| getArg(1): [RefExpr] &field
# 85| getExpr(): [PathExpr,VariableAccess] field
# 85| getExpr(): [VariableAccess] field
# 85| getPath(): [Path] field
# 85| getSegment(): [PathSegment] field
# 85| getIdentifier(): [NameRef] field
@@ -760,7 +760,7 @@ macro_expansion.rs:
# 83| getArgList(): [ArgList] ArgList
# 83| getArg(0): [StringLiteralExpr] "MyDerive"
# 83| getIdentifier(): [NameRef] debug_struct
# 83| getReceiver(): [PathExpr,VariableAccess] f
# 83| getReceiver(): [VariableAccess] f
# 83| getPath(): [Path] f
# 83| getSegment(): [PathSegment] f
# 83| getIdentifier(): [NameRef] f
@@ -836,11 +836,11 @@ macro_expansion.rs:
# 89| getStmtList(): [StmtList] StmtList
# 89| getTailExpr(): [MatchExpr] match ... { ... }
# 88| getScrutinee(): [TupleExpr] TupleExpr
# 88| getField(0): [PathExpr,VariableAccess] self
# 88| getField(0): [VariableAccess] self
# 88| getPath(): [Path] self
# 88| getSegment(): [PathSegment] self
# 88| getIdentifier(): [NameRef] self
# 88| getField(1): [PathExpr,VariableAccess] other
# 88| getField(1): [VariableAccess] other
# 88| getPath(): [Path] other
# 88| getSegment(): [PathSegment] other
# 88| getIdentifier(): [NameRef] other
@@ -1076,7 +1076,7 @@ proc_macro.rs:
# 6| getMacroCallExpansion(): [MatchExpr] match ... { ... }
# 6| getScrutinee(): [CallExpr] ...::parse::<...>(...)
# 6| getArgList(): [ArgList] ArgList
# 6| getArg(0): [PathExpr,VariableAccess] attr
# 6| getArg(0): [VariableAccess] attr
# 6| getPath(): [Path] attr
# 6| getSegment(): [PathSegment] attr
# 6| getIdentifier(): [NameRef] attr
@@ -1098,7 +1098,7 @@ proc_macro.rs:
# 6| getIdentifier(): [NameRef] parse
# 6| getMatchArmList(): [MatchArmList] MatchArmList
# 6| getArm(0): [MatchArm] ... => data
# 6| getExpr(): [PathExpr,VariableAccess] data
# 6| getExpr(): [VariableAccess] data
# 6| getPath(): [Path] data
# 6| getSegment(): [PathSegment] data
# 6| getIdentifier(): [NameRef] data
@@ -1124,7 +1124,7 @@ proc_macro.rs:
# 6| getArg(0): [MethodCallExpr] err.to_compile_error()
# 6| getArgList(): [ArgList] ArgList
# 6| getIdentifier(): [NameRef] to_compile_error
# 6| getReceiver(): [PathExpr,VariableAccess] err
# 6| getReceiver(): [VariableAccess] err
# 6| getPath(): [Path] err
# 6| getSegment(): [PathSegment] err
# 6| getIdentifier(): [NameRef] err
@@ -1168,7 +1168,7 @@ proc_macro.rs:
# 7| getMacroCallExpansion(): [MatchExpr] match ... { ... }
# 7| getScrutinee(): [CallExpr] ...::parse::<...>(...)
# 7| getArgList(): [ArgList] ArgList
# 7| getArg(0): [PathExpr,VariableAccess] item
# 7| getArg(0): [VariableAccess] item
# 7| getPath(): [Path] item
# 7| getSegment(): [PathSegment] item
# 7| getIdentifier(): [NameRef] item
@@ -1190,7 +1190,7 @@ proc_macro.rs:
# 7| getIdentifier(): [NameRef] parse
# 7| getMatchArmList(): [MatchArmList] MatchArmList
# 7| getArm(0): [MatchArm] ... => data
# 7| getExpr(): [PathExpr,VariableAccess] data
# 7| getExpr(): [VariableAccess] data
# 7| getPath(): [Path] data
# 7| getSegment(): [PathSegment] data
# 7| getIdentifier(): [NameRef] data
@@ -1216,7 +1216,7 @@ proc_macro.rs:
# 7| getArg(0): [MethodCallExpr] err.to_compile_error()
# 7| getArgList(): [ArgList] ArgList
# 7| getIdentifier(): [NameRef] to_compile_error
# 7| getReceiver(): [PathExpr,VariableAccess] err
# 7| getReceiver(): [VariableAccess] err
# 7| getPath(): [Path] err
# 7| getSegment(): [PathSegment] err
# 7| getIdentifier(): [NameRef] err
@@ -1273,7 +1273,7 @@ proc_macro.rs:
# 10| getInitializer(): [MethodCallExpr] ast.clone()
# 10| getArgList(): [ArgList] ArgList
# 10| getIdentifier(): [NameRef] clone
# 10| getReceiver(): [PathExpr,VariableAccess] ast
# 10| getReceiver(): [VariableAccess] ast
# 10| getPath(): [Path] ast
# 10| getSegment(): [PathSegment] ast
# 10| getIdentifier(): [NameRef] ast
@@ -1283,7 +1283,7 @@ proc_macro.rs:
# 11| getExpr(): [AssignmentExpr] ... = ...
# 11| getLhs(): [FieldExpr] ... .ident
# 11| getContainer(): [FieldExpr] new_ast.sig
# 11| getContainer(): [PathExpr,VariableAccess] new_ast
# 11| getContainer(): [VariableAccess] new_ast
# 11| getPath(): [Path] new_ast
# 11| getSegment(): [PathSegment] new_ast
# 11| getIdentifier(): [NameRef] new_ast
@@ -1320,14 +1320,14 @@ proc_macro.rs:
# 11| getArg(0): [FormatArgsArg] FormatArgsArg
# 11| getExpr(): [FieldExpr] ... .ident
# 11| getContainer(): [FieldExpr] ast.sig
# 11| getContainer(): [PathExpr,VariableAccess] ast
# 11| getContainer(): [VariableAccess] ast
# 11| getPath(): [Path] ast
# 11| getSegment(): [PathSegment] ast
# 11| getIdentifier(): [NameRef] ast
# 11| getIdentifier(): [NameRef] sig
# 11| getIdentifier(): [NameRef] ident
# 11| getArg(1): [FormatArgsArg] FormatArgsArg
# 11| getExpr(): [PathExpr,VariableAccess] i
# 11| getExpr(): [VariableAccess] i
# 11| getPath(): [Path] i
# 11| getSegment(): [PathSegment] i
# 11| getIdentifier(): [NameRef] i
@@ -1359,7 +1359,7 @@ proc_macro.rs:
# 11| getIdentifier(): [NameRef] span
# 11| getReceiver(): [FieldExpr] ... .ident
# 11| getContainer(): [FieldExpr] ast.sig
# 11| getContainer(): [PathExpr,VariableAccess] ast
# 11| getContainer(): [VariableAccess] ast
# 11| getPath(): [Path] ast
# 11| getSegment(): [PathSegment] ast
# 11| getIdentifier(): [NameRef] ast
@@ -1375,14 +1375,14 @@ proc_macro.rs:
# 11| getIdentifier(): [NameRef] Ident
# 11| getSegment(): [PathSegment] new
# 11| getIdentifier(): [NameRef] new
# 12| getTailExpr(): [PathExpr,VariableAccess] new_ast
# 12| getTailExpr(): [VariableAccess] new_ast
# 12| getPath(): [Path] new_ast
# 12| getSegment(): [PathSegment] new_ast
# 12| getIdentifier(): [NameRef] new_ast
# 9| getIdentifier(): [NameRef] map
# 8| getReceiver(): [ParenExpr] (...)
# 8| getExpr(): [RangeExpr] 0..number
# 8| getEnd(): [PathExpr,VariableAccess] number
# 8| getEnd(): [VariableAccess] number
# 8| getPath(): [Path] number
# 8| getSegment(): [PathSegment] number
# 8| getIdentifier(): [NameRef] number
@@ -1614,7 +1614,7 @@ proc_macro.rs:
# 16| getInitializer(): [MethodCallExpr] items.quote_into_iter()
# 15| getArgList(): [ArgList] ArgList
# 15| getIdentifier(): [NameRef] quote_into_iter
# 16| getReceiver(): [PathExpr,VariableAccess] items
# 16| getReceiver(): [VariableAccess] items
# 16| getPath(): [Path] items
# 16| getSegment(): [PathSegment] items
# 16| getIdentifier(): [NameRef] items
@@ -1625,11 +1625,11 @@ proc_macro.rs:
# 15| getName(): [Name] i
# 15| getStatement(1): [LetStmt] let ... = ...
# 15| getInitializer(): [BinaryExpr] ... | ...
# 15| getLhs(): [PathExpr,VariableAccess] has_iter
# 15| getLhs(): [VariableAccess] has_iter
# 15| getPath(): [Path] has_iter
# 15| getSegment(): [PathSegment] has_iter
# 15| getIdentifier(): [NameRef] has_iter
# 15| getRhs(): [PathExpr,VariableAccess] i
# 15| getRhs(): [VariableAccess] i
# 15| getPath(): [Path] i
# 15| getSegment(): [PathSegment] i
# 15| getIdentifier(): [NameRef] i
@@ -1646,7 +1646,7 @@ proc_macro.rs:
# 16| getTokenTree(): [TokenTree] TokenTree
# 15| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr
# 15| getStatement(3): [LetStmt] let _ = has_iter
# 15| getInitializer(): [PathExpr,VariableAccess] has_iter
# 15| getInitializer(): [VariableAccess] has_iter
# 15| getPath(): [Path] has_iter
# 15| getSegment(): [PathSegment] has_iter
# 15| getIdentifier(): [NameRef] has_iter
@@ -1764,7 +1764,7 @@ proc_macro.rs:
# 16| getScrutinee(): [MethodCallExpr] items.next()
# 15| getArgList(): [ArgList] ArgList
# 15| getIdentifier(): [NameRef] next
# 16| getReceiver(): [PathExpr,VariableAccess] items
# 16| getReceiver(): [VariableAccess] items
# 16| getPath(): [Path] items
# 16| getSegment(): [PathSegment] items
# 16| getIdentifier(): [NameRef] items
@@ -1772,7 +1772,7 @@ proc_macro.rs:
# 15| getArm(0): [MatchArm] ... => ...
# 15| getExpr(): [CallExpr] ...::RepInterp(...)
# 15| getArgList(): [ArgList] ArgList
# 15| getArg(0): [PathExpr] _x
# 15| getArg(0): [VariableAccess] _x
# 15| getPath(): [Path] _x
# 15| getSegment(): [PathSegment] _x
# 15| getIdentifier(): [NameRef] _x
@@ -1876,12 +1876,12 @@ proc_macro.rs:
# 16| getExpr(): [CallExpr] ...::to_tokens(...)
# 16| getArgList(): [ArgList] ArgList
# 16| getArg(0): [RefExpr] &items
# 16| getExpr(): [PathExpr,VariableAccess] items
# 16| getExpr(): [VariableAccess] items
# 16| getPath(): [Path] items
# 16| getSegment(): [PathSegment] items
# 16| getIdentifier(): [NameRef] items
# 15| getArg(1): [RefExpr] &mut _s
# 15| getExpr(): [PathExpr] _s
# 15| getExpr(): [VariableAccess] _s
# 15| getPath(): [Path] _s
# 15| getSegment(): [PathSegment] _s
# 15| getIdentifier(): [NameRef] _s
@@ -1993,7 +1993,7 @@ proc_macro.rs:
# 15| getIdentifier(): [NameRef] quote_token_with_context
# 16| getTokenTree(): [TokenTree] TokenTree
# 15| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr
# 15| getTailExpr(): [PathExpr] _s
# 15| getTailExpr(): [VariableAccess] _s
# 15| getPath(): [Path] _s
# 15| getSegment(): [PathSegment] _s
# 15| getIdentifier(): [NameRef] _s
@@ -2040,7 +2040,7 @@ proc_macro.rs:
# 22| getMacroCallExpansion(): [MatchExpr] match ... { ... }
# 22| getScrutinee(): [CallExpr] ...::parse::<...>(...)
# 22| getArgList(): [ArgList] ArgList
# 22| getArg(0): [PathExpr,VariableAccess] item
# 22| getArg(0): [VariableAccess] item
# 22| getPath(): [Path] item
# 22| getSegment(): [PathSegment] item
# 22| getIdentifier(): [NameRef] item
@@ -2062,7 +2062,7 @@ proc_macro.rs:
# 22| getIdentifier(): [NameRef] parse
# 22| getMatchArmList(): [MatchArmList] MatchArmList
# 22| getArm(0): [MatchArm] ... => data
# 22| getExpr(): [PathExpr,VariableAccess] data
# 22| getExpr(): [VariableAccess] data
# 22| getPath(): [Path] data
# 22| getSegment(): [PathSegment] data
# 22| getIdentifier(): [NameRef] data
@@ -2088,7 +2088,7 @@ proc_macro.rs:
# 22| getArg(0): [MethodCallExpr] err.to_compile_error()
# 22| getArgList(): [ArgList] ArgList
# 22| getIdentifier(): [NameRef] to_compile_error
# 22| getReceiver(): [PathExpr,VariableAccess] err
# 22| getReceiver(): [VariableAccess] err
# 22| getPath(): [Path] err
# 22| getSegment(): [PathSegment] err
# 22| getIdentifier(): [NameRef] err
@@ -2123,7 +2123,7 @@ proc_macro.rs:
# 23| getInitializer(): [MethodCallExpr] ast.clone()
# 23| getArgList(): [ArgList] ArgList
# 23| getIdentifier(): [NameRef] clone
# 23| getReceiver(): [PathExpr,VariableAccess] ast
# 23| getReceiver(): [VariableAccess] ast
# 23| getPath(): [Path] ast
# 23| getSegment(): [PathSegment] ast
# 23| getIdentifier(): [NameRef] ast
@@ -2133,7 +2133,7 @@ proc_macro.rs:
# 24| getExpr(): [AssignmentExpr] ... = ...
# 24| getLhs(): [FieldExpr] ... .ident
# 24| getContainer(): [FieldExpr] new_ast.sig
# 24| getContainer(): [PathExpr,VariableAccess] new_ast
# 24| getContainer(): [VariableAccess] new_ast
# 24| getPath(): [Path] new_ast
# 24| getSegment(): [PathSegment] new_ast
# 24| getIdentifier(): [NameRef] new_ast
@@ -2170,7 +2170,7 @@ proc_macro.rs:
# 24| getArg(0): [FormatArgsArg] FormatArgsArg
# 24| getExpr(): [FieldExpr] ... .ident
# 24| getContainer(): [FieldExpr] ast.sig
# 24| getContainer(): [PathExpr,VariableAccess] ast
# 24| getContainer(): [VariableAccess] ast
# 24| getPath(): [Path] ast
# 24| getSegment(): [PathSegment] ast
# 24| getIdentifier(): [NameRef] ast
@@ -2203,7 +2203,7 @@ proc_macro.rs:
# 24| getIdentifier(): [NameRef] span
# 24| getReceiver(): [FieldExpr] ... .ident
# 24| getContainer(): [FieldExpr] ast.sig
# 24| getContainer(): [PathExpr,VariableAccess] ast
# 24| getContainer(): [VariableAccess] ast
# 24| getPath(): [Path] ast
# 24| getSegment(): [PathSegment] ast
# 24| getIdentifier(): [NameRef] ast
@@ -2317,12 +2317,12 @@ proc_macro.rs:
# 26| getExpr(): [CallExpr] ...::to_tokens(...)
# 26| getArgList(): [ArgList] ArgList
# 26| getArg(0): [RefExpr] &ast
# 26| getExpr(): [PathExpr,VariableAccess] ast
# 26| getExpr(): [VariableAccess] ast
# 26| getPath(): [Path] ast
# 26| getSegment(): [PathSegment] ast
# 26| getIdentifier(): [NameRef] ast
# 25| getArg(1): [RefExpr] &mut _s
# 25| getExpr(): [PathExpr] _s
# 25| getExpr(): [VariableAccess] _s
# 25| getPath(): [Path] _s
# 25| getSegment(): [PathSegment] _s
# 25| getIdentifier(): [NameRef] _s
@@ -2362,12 +2362,12 @@ proc_macro.rs:
# 27| getExpr(): [CallExpr] ...::to_tokens(...)
# 27| getArgList(): [ArgList] ArgList
# 27| getArg(0): [RefExpr] &new_ast
# 27| getExpr(): [PathExpr,VariableAccess] new_ast
# 27| getExpr(): [VariableAccess] new_ast
# 27| getPath(): [Path] new_ast
# 27| getSegment(): [PathSegment] new_ast
# 27| getIdentifier(): [NameRef] new_ast
# 25| getArg(1): [RefExpr] &mut _s
# 25| getExpr(): [PathExpr] _s
# 25| getExpr(): [VariableAccess] _s
# 25| getPath(): [Path] _s
# 25| getSegment(): [PathSegment] _s
# 25| getIdentifier(): [NameRef] _s
@@ -2424,7 +2424,7 @@ proc_macro.rs:
# 25| getIdentifier(): [NameRef] quote_token_with_context
# 27| getTokenTree(): [TokenTree] TokenTree
# 25| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr
# 25| getTailExpr(): [PathExpr] _s
# 25| getTailExpr(): [VariableAccess] _s
# 25| getPath(): [Path] _s
# 25| getSegment(): [PathSegment] _s
# 25| getIdentifier(): [NameRef] _s
@@ -2504,7 +2504,7 @@ proc_macro.rs:
# 38| getMacroCallExpansion(): [MatchExpr] match ... { ... }
# 38| getScrutinee(): [CallExpr] ...::parse::<...>(...)
# 38| getArgList(): [ArgList] ArgList
# 38| getArg(0): [PathExpr,VariableAccess] input
# 38| getArg(0): [VariableAccess] input
# 38| getPath(): [Path] input
# 38| getSegment(): [PathSegment] input
# 38| getIdentifier(): [NameRef] input
@@ -2526,7 +2526,7 @@ proc_macro.rs:
# 38| getIdentifier(): [NameRef] parse
# 38| getMatchArmList(): [MatchArmList] MatchArmList
# 38| getArm(0): [MatchArm] ... => data
# 38| getExpr(): [PathExpr,VariableAccess] data
# 38| getExpr(): [VariableAccess] data
# 38| getPath(): [Path] data
# 38| getSegment(): [PathSegment] data
# 38| getIdentifier(): [NameRef] data
@@ -2552,7 +2552,7 @@ proc_macro.rs:
# 38| getArg(0): [MethodCallExpr] err.to_compile_error()
# 38| getArgList(): [ArgList] ArgList
# 38| getIdentifier(): [NameRef] to_compile_error
# 38| getReceiver(): [PathExpr,VariableAccess] err
# 38| getReceiver(): [VariableAccess] err
# 38| getPath(): [Path] err
# 38| getSegment(): [PathSegment] err
# 38| getIdentifier(): [NameRef] err
@@ -2586,7 +2586,7 @@ proc_macro.rs:
# 39| getStatement(1): [LetStmt] let ... = ...
# 39| getInitializer(): [RefExpr] &...
# 39| getExpr(): [FieldExpr] ast.ident
# 39| getContainer(): [PathExpr,VariableAccess] ast
# 39| getContainer(): [VariableAccess] ast
# 39| getPath(): [Path] ast
# 39| getSegment(): [PathSegment] ast
# 39| getIdentifier(): [NameRef] ast
@@ -2623,7 +2623,7 @@ proc_macro.rs:
# 40| getTokenTree(): [TokenTree] TokenTree
# 40| getMacroCallExpansion(): [FormatArgsExpr] FormatArgsExpr
# 40| getArg(0): [FormatArgsArg] FormatArgsArg
# 40| getExpr(): [PathExpr,VariableAccess] name
# 40| getExpr(): [VariableAccess] name
# 40| getPath(): [Path] name
# 40| getSegment(): [PathSegment] name
# 40| getIdentifier(): [NameRef] name
@@ -2652,7 +2652,7 @@ proc_macro.rs:
# 40| getArg(1): [MethodCallExpr] name.span()
# 40| getArgList(): [ArgList] ArgList
# 40| getIdentifier(): [NameRef] span
# 40| getReceiver(): [PathExpr,VariableAccess] name
# 40| getReceiver(): [VariableAccess] name
# 40| getPath(): [Path] name
# 40| getSegment(): [PathSegment] name
# 40| getIdentifier(): [NameRef] name
@@ -2776,7 +2776,7 @@ proc_macro.rs:
# 42| getExpr(): [CallExpr] ...::push_ident(...)
# 42| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -2812,12 +2812,12 @@ proc_macro.rs:
# 42| getExpr(): [CallExpr] ...::to_tokens(...)
# 42| getArgList(): [ArgList] ArgList
# 42| getArg(0): [RefExpr] &const_ident
# 42| getExpr(): [PathExpr,VariableAccess] const_ident
# 42| getExpr(): [VariableAccess] const_ident
# 42| getPath(): [Path] const_ident
# 42| getSegment(): [PathSegment] const_ident
# 42| getIdentifier(): [NameRef] const_ident
# 41| getArg(1): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -2867,7 +2867,7 @@ proc_macro.rs:
# 41| getExpr(): [CallExpr] ...::push_colon(...)
# 41| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -2906,7 +2906,7 @@ proc_macro.rs:
# 42| getExpr(): [CallExpr] ...::push_ident(...)
# 42| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -2952,7 +2952,7 @@ proc_macro.rs:
# 41| getExpr(): [CallExpr] ...::push_eq(...)
# 41| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -2991,7 +2991,7 @@ proc_macro.rs:
# 42| getExpr(): [CallExpr] ...::parse(...)
# 42| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3037,7 +3037,7 @@ proc_macro.rs:
# 41| getExpr(): [CallExpr] ...::push_semi(...)
# 41| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3076,7 +3076,7 @@ proc_macro.rs:
# 44| getExpr(): [CallExpr] ...::push_ident(...)
# 44| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3122,7 +3122,7 @@ proc_macro.rs:
# 44| getExpr(): [CallExpr] ...::push_ident(...)
# 44| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3168,7 +3168,7 @@ proc_macro.rs:
# 44| getExpr(): [CallExpr] ...::push_ident(...)
# 44| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3204,12 +3204,12 @@ proc_macro.rs:
# 44| getExpr(): [CallExpr] ...::to_tokens(...)
# 44| getArgList(): [ArgList] ArgList
# 44| getArg(0): [RefExpr] &name
# 44| getExpr(): [PathExpr,VariableAccess] name
# 44| getExpr(): [VariableAccess] name
# 44| getPath(): [Path] name
# 44| getSegment(): [PathSegment] name
# 44| getIdentifier(): [NameRef] name
# 41| getArg(1): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3259,7 +3259,7 @@ proc_macro.rs:
# 45| getExpr(): [CallExpr] ...::push_group(...)
# 45| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3384,7 +3384,7 @@ proc_macro.rs:
# 45| getExpr(): [CallExpr] ...::push_ident(...)
# 45| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3430,7 +3430,7 @@ proc_macro.rs:
# 45| getExpr(): [CallExpr] ...::push_ident(...)
# 45| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3476,7 +3476,7 @@ proc_macro.rs:
# 41| getExpr(): [CallExpr] ...::push_group(...)
# 41| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3552,7 +3552,7 @@ proc_macro.rs:
# 41| getExpr(): [CallExpr] ...::push_rarrow(...)
# 41| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3591,7 +3591,7 @@ proc_macro.rs:
# 45| getExpr(): [CallExpr] ...::push_ident(...)
# 45| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3637,7 +3637,7 @@ proc_macro.rs:
# 46| getExpr(): [CallExpr] ...::push_group(...)
# 46| getArgList(): [ArgList] ArgList
# 41| getArg(0): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3687,12 +3687,12 @@ proc_macro.rs:
# 46| getExpr(): [CallExpr] ...::to_tokens(...)
# 46| getArgList(): [ArgList] ArgList
# 46| getArg(0): [RefExpr] &const_ident
# 46| getExpr(): [PathExpr,VariableAccess] const_ident
# 46| getExpr(): [VariableAccess] const_ident
# 46| getPath(): [Path] const_ident
# 46| getSegment(): [PathSegment] const_ident
# 46| getIdentifier(): [NameRef] const_ident
# 41| getArg(1): [RefExpr] &mut _s
# 41| getExpr(): [PathExpr] _s
# 41| getExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3706,7 +3706,7 @@ proc_macro.rs:
# 41| getIdentifier(): [NameRef] ToTokens
# 41| getSegment(): [PathSegment] to_tokens
# 41| getIdentifier(): [NameRef] to_tokens
# 41| getTailExpr(): [PathExpr] _s
# 41| getTailExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3752,7 +3752,7 @@ proc_macro.rs:
# 41| getIdentifier(): [NameRef] quote_token_with_context
# 45| getTokenTree(): [TokenTree] TokenTree
# 41| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr
# 41| getTailExpr(): [PathExpr] _s
# 41| getTailExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s
@@ -3798,7 +3798,7 @@ proc_macro.rs:
# 41| getIdentifier(): [NameRef] quote_token_with_context
# 44| getTokenTree(): [TokenTree] TokenTree
# 41| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr
# 41| getTailExpr(): [PathExpr] _s
# 41| getTailExpr(): [VariableAccess] _s
# 41| getPath(): [Path] _s
# 41| getSegment(): [PathSegment] _s
# 41| getIdentifier(): [NameRef] _s

View File

@@ -4,8 +4,10 @@
| test.rs:17:31:17:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:22:22:22:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:22:22:22:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:26:18:26:29 | ...::read_dir | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:29:22:29:25 | path | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:43:27:43:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:51:52:51:59 | read_dir | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:54:22:54:25 | path | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:55:27:55:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). |
| test.rs:65:22:65:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). |

View File

@@ -23,7 +23,7 @@ fn test_fs() -> Result<(), Box<dyn std::error::Error>> {
sink(buffer); // $ hasTaintFlow="file.txt"
}
for entry in fs::read_dir("directory")? {
for entry in fs::read_dir("directory")? { // $ Alert[rust/summary/taint-sources]
let e = entry?;
let path = e.path(); // $ Alert[rust/summary/taint-sources]
@@ -48,7 +48,7 @@ fn test_fs() -> Result<(), Box<dyn std::error::Error>> {
sink(file_name.clone().as_encoded_bytes()); // $ MISSING: hasTaintFlow
sink(file_name); // $ hasTaintFlow
}
for entry in std::path::Path::new("directory").read_dir()? {
for entry in std::path::Path::new("directory").read_dir()? { // $ Alert[rust/summary/taint-sources]
let e = entry?;
let path = e.path(); // $ Alert[rust/summary/taint-sources]

View File

@@ -1,6 +1,8 @@
| struct Array | |
| struct Ptr | |
| struct PtrMut | |
| struct Ref | |
| struct RefMut | |
| struct Slice | |
| struct Tuple0 | |
| struct Tuple1 | |

View File

@@ -790,6 +790,49 @@ mod impl_with_attribute_macro {
} // impl_with_attribute_macro::test
}
mod patterns {
#[rustfmt::skip]
pub fn test() -> Option<i32> { // $ item=Option $ item=i32
let x = Some(42); // $ item=Some
let y : Option<i32> = match x { // $ item=Option $ item=i32
Some(y) => { // $ item=Some
None // $ item=None
}
None => // $ item=None
None // $ item=None
};
match y {
N0ne => // local variable
N0ne
}
} // patterns::test
#[rustfmt::skip]
fn test2() -> Option<i32> { // $ item=Option $ item=i32
let test_alias = test; // $ item=patterns::test
let test = test_alias();
test
}
#[rustfmt::skip]
const z: i32 // $ item=i32
= 0; // constz
#[rustfmt::skip]
fn test3() {
let x = Some(0); // $ item=Some
match x {
Some(x) // $ item=Some
=> x,
_ => 0
};
match x {
Some(z) => z, // $ item=Some item=constz
_ => 0
};
}
}
fn main() {
my::nested::nested1::nested2::f(); // $ item=I4
my::f(); // $ item=I38
@@ -826,4 +869,5 @@ fn main() {
AStruct::z_on_type(); // $ item=I124
AStruct {}.z_on_instance(); // $ item=I123 item=I125
impl_with_attribute_macro::test(); // $ item=impl_with_attribute_macro::test
patterns::test(); // $ item=patterns::test
}

View File

@@ -32,6 +32,7 @@ mod
| main.rs:629:1:697:1 | mod m24 |
| main.rs:714:1:766:1 | mod associated_types |
| main.rs:772:1:791:1 | mod impl_with_attribute_macro |
| main.rs:793:1:834:1 | mod patterns |
| my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:20:1:20:12 | mod my3 |
| my2/mod.rs:22:1:23:10 | mod mymod |
@@ -72,7 +73,7 @@ resolvePath
| main.rs:37:17:37:24 | ...::f | main.rs:26:9:28:9 | fn f |
| main.rs:39:17:39:23 | println | {EXTERNAL LOCATION} | MacroRules |
| main.rs:40:17:40:17 | f | main.rs:26:9:28:9 | fn f |
| main.rs:47:9:47:13 | super | main.rs:1:1:829:2 | SourceFile |
| main.rs:47:9:47:13 | super | main.rs:1:1:873:2 | SourceFile |
| main.rs:47:9:47:17 | ...::m1 | main.rs:20:1:44:1 | mod m1 |
| main.rs:47:9:47:21 | ...::m2 | main.rs:25:5:43:5 | mod m2 |
| main.rs:47:9:47:24 | ...::g | main.rs:30:9:34:9 | fn g |
@@ -87,7 +88,7 @@ resolvePath
| main.rs:68:17:68:19 | Foo | main.rs:66:9:66:21 | struct Foo |
| main.rs:71:13:71:15 | Foo | main.rs:60:5:60:17 | struct Foo |
| main.rs:73:5:73:5 | f | main.rs:62:5:69:5 | fn f |
| main.rs:75:5:75:8 | self | main.rs:1:1:829:2 | SourceFile |
| main.rs:75:5:75:8 | self | main.rs:1:1:873:2 | SourceFile |
| main.rs:75:5:75:11 | ...::i | main.rs:78:1:90:1 | fn i |
| main.rs:79:5:79:11 | println | {EXTERNAL LOCATION} | MacroRules |
| main.rs:81:13:81:15 | Foo | main.rs:55:1:55:13 | struct Foo |
@@ -109,7 +110,7 @@ resolvePath
| main.rs:112:9:112:15 | println | {EXTERNAL LOCATION} | MacroRules |
| main.rs:118:9:118:15 | println | {EXTERNAL LOCATION} | MacroRules |
| main.rs:122:9:122:15 | println | {EXTERNAL LOCATION} | MacroRules |
| main.rs:125:13:125:17 | super | main.rs:1:1:829:2 | SourceFile |
| main.rs:125:13:125:17 | super | main.rs:1:1:873:2 | SourceFile |
| main.rs:125:13:125:21 | ...::m5 | main.rs:110:1:114:1 | mod m5 |
| main.rs:126:9:126:9 | f | main.rs:111:5:113:5 | fn f |
| main.rs:126:9:126:9 | f | main.rs:117:5:119:5 | fn f |
@@ -397,77 +398,97 @@ resolvePath
| main.rs:781:21:781:23 | i64 | {EXTERNAL LOCATION} | struct i64 |
| main.rs:783:11:783:13 | i64 | {EXTERNAL LOCATION} | struct i64 |
| main.rs:789:17:789:19 | Foo | main.rs:774:5:774:15 | struct Foo |
| main.rs:794:5:794:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:794:5:794:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:794:5:794:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
| main.rs:794:5:794:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| main.rs:794:5:794:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
| main.rs:795:5:795:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:795:5:795:9 | ...::f | my.rs:5:1:7:1 | fn f |
| main.rs:796:5:796:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| main.rs:796:5:796:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| main.rs:796:5:796:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:796:5:796:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:797:5:797:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:798:5:798:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:799:5:799:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
| main.rs:799:5:799:12 | ...::h | main.rs:57:1:76:1 | fn h |
| main.rs:800:5:800:6 | m1 | main.rs:20:1:44:1 | mod m1 |
| main.rs:800:5:800:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 |
| main.rs:800:5:800:13 | ...::g | main.rs:30:9:34:9 | fn g |
| main.rs:801:5:801:6 | m1 | main.rs:20:1:44:1 | mod m1 |
| main.rs:801:5:801:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 |
| main.rs:801:5:801:14 | ...::m3 | main.rs:36:9:42:9 | mod m3 |
| main.rs:801:5:801:17 | ...::h | main.rs:37:27:41:13 | fn h |
| main.rs:802:5:802:6 | m4 | main.rs:46:1:53:1 | mod m4 |
| main.rs:802:5:802:9 | ...::i | main.rs:49:5:52:5 | fn i |
| main.rs:803:5:803:5 | h | main.rs:57:1:76:1 | fn h |
| main.rs:804:5:804:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:805:5:805:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:806:5:806:5 | j | main.rs:104:1:108:1 | fn j |
| main.rs:807:5:807:6 | m6 | main.rs:116:1:128:1 | mod m6 |
| main.rs:807:5:807:9 | ...::g | main.rs:121:5:127:5 | fn g |
| main.rs:808:5:808:6 | m7 | main.rs:130:1:149:1 | mod m7 |
| main.rs:808:5:808:9 | ...::f | main.rs:141:5:148:5 | fn f |
| main.rs:809:5:809:6 | m8 | main.rs:151:1:205:1 | mod m8 |
| main.rs:809:5:809:9 | ...::g | main.rs:189:5:204:5 | fn g |
| main.rs:810:5:810:6 | m9 | main.rs:207:1:215:1 | mod m9 |
| main.rs:810:5:810:9 | ...::f | main.rs:210:5:214:5 | fn f |
| main.rs:811:5:811:7 | m11 | main.rs:238:1:275:1 | mod m11 |
| main.rs:811:5:811:10 | ...::f | main.rs:243:5:246:5 | fn f |
| main.rs:812:5:812:7 | m15 | main.rs:306:1:375:1 | mod m15 |
| main.rs:812:5:812:10 | ...::f | main.rs:362:5:374:5 | fn f |
| main.rs:813:5:813:7 | m16 | main.rs:377:1:469:1 | mod m16 |
| main.rs:813:5:813:10 | ...::f | main.rs:444:5:468:5 | fn f |
| main.rs:814:5:814:20 | trait_visibility | main.rs:471:1:521:1 | mod trait_visibility |
| main.rs:814:5:814:23 | ...::f | main.rs:498:5:520:5 | fn f |
| main.rs:815:5:815:7 | m17 | main.rs:523:1:553:1 | mod m17 |
| main.rs:815:5:815:10 | ...::f | main.rs:547:5:552:5 | fn f |
| main.rs:816:5:816:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
| main.rs:816:5:816:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
| main.rs:817:5:817:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
| main.rs:817:5:817:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
| main.rs:818:5:818:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 |
| main.rs:818:5:818:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
| main.rs:819:5:819:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| main.rs:820:5:820:12 | my_alias | main.rs:1:1:1:7 | mod my |
| main.rs:820:5:820:22 | ...::nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| main.rs:821:5:821:7 | m18 | main.rs:555:1:573:1 | mod m18 |
| main.rs:821:5:821:12 | ...::m19 | main.rs:560:5:572:5 | mod m19 |
| main.rs:821:5:821:17 | ...::m20 | main.rs:565:9:571:9 | mod m20 |
| main.rs:821:5:821:20 | ...::g | main.rs:566:13:570:13 | fn g |
| main.rs:822:5:822:7 | m23 | main.rs:602:1:627:1 | mod m23 |
| main.rs:822:5:822:10 | ...::f | main.rs:622:5:626:5 | fn f |
| main.rs:823:5:823:7 | m24 | main.rs:629:1:697:1 | mod m24 |
| main.rs:823:5:823:10 | ...::f | main.rs:683:5:696:5 | fn f |
| main.rs:824:5:824:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) |
| main.rs:824:5:824:11 | ...::h | main.rs:57:1:76:1 | fn h |
| main.rs:825:5:825:13 | z_changed | main.rs:702:1:702:9 | fn z_changed |
| main.rs:826:5:826:11 | AStruct | main.rs:704:1:704:17 | struct AStruct |
| main.rs:826:5:826:22 | ...::z_on_type | main.rs:708:5:708:17 | fn z_on_type |
| main.rs:827:5:827:11 | AStruct | main.rs:704:1:704:17 | struct AStruct |
| main.rs:828:5:828:29 | impl_with_attribute_macro | main.rs:772:1:791:1 | mod impl_with_attribute_macro |
| main.rs:828:5:828:35 | ...::test | main.rs:787:5:790:5 | fn test |
| main.rs:795:22:795:32 | Option::<...> | {EXTERNAL LOCATION} | enum Option |
| main.rs:795:29:795:31 | i32 | {EXTERNAL LOCATION} | struct i32 |
| main.rs:796:17:796:20 | Some | {EXTERNAL LOCATION} | Some |
| main.rs:797:17:797:27 | Option::<...> | {EXTERNAL LOCATION} | enum Option |
| main.rs:797:24:797:26 | i32 | {EXTERNAL LOCATION} | struct i32 |
| main.rs:798:13:798:16 | Some | {EXTERNAL LOCATION} | Some |
| main.rs:799:17:799:20 | None | {EXTERNAL LOCATION} | None |
| main.rs:801:13:801:16 | None | {EXTERNAL LOCATION} | None |
| main.rs:802:17:802:20 | None | {EXTERNAL LOCATION} | None |
| main.rs:811:19:811:29 | Option::<...> | {EXTERNAL LOCATION} | enum Option |
| main.rs:811:26:811:28 | i32 | {EXTERNAL LOCATION} | struct i32 |
| main.rs:812:26:812:29 | test | main.rs:794:5:808:5 | fn test |
| main.rs:818:14:818:16 | i32 | {EXTERNAL LOCATION} | struct i32 |
| main.rs:823:17:823:20 | Some | {EXTERNAL LOCATION} | Some |
| main.rs:825:13:825:16 | Some | {EXTERNAL LOCATION} | Some |
| main.rs:830:13:830:16 | Some | {EXTERNAL LOCATION} | Some |
| main.rs:830:18:830:18 | z | main.rs:817:5:819:12 | Const |
| main.rs:830:24:830:24 | z | main.rs:817:5:819:12 | Const |
| main.rs:837:5:837:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:837:5:837:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:837:5:837:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
| main.rs:837:5:837:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| main.rs:837:5:837:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
| main.rs:838:5:838:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:838:5:838:9 | ...::f | my.rs:5:1:7:1 | fn f |
| main.rs:839:5:839:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| main.rs:839:5:839:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| main.rs:839:5:839:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:839:5:839:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:840:5:840:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:841:5:841:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:842:5:842:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
| main.rs:842:5:842:12 | ...::h | main.rs:57:1:76:1 | fn h |
| main.rs:843:5:843:6 | m1 | main.rs:20:1:44:1 | mod m1 |
| main.rs:843:5:843:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 |
| main.rs:843:5:843:13 | ...::g | main.rs:30:9:34:9 | fn g |
| main.rs:844:5:844:6 | m1 | main.rs:20:1:44:1 | mod m1 |
| main.rs:844:5:844:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 |
| main.rs:844:5:844:14 | ...::m3 | main.rs:36:9:42:9 | mod m3 |
| main.rs:844:5:844:17 | ...::h | main.rs:37:27:41:13 | fn h |
| main.rs:845:5:845:6 | m4 | main.rs:46:1:53:1 | mod m4 |
| main.rs:845:5:845:9 | ...::i | main.rs:49:5:52:5 | fn i |
| main.rs:846:5:846:5 | h | main.rs:57:1:76:1 | fn h |
| main.rs:847:5:847:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:848:5:848:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:849:5:849:5 | j | main.rs:104:1:108:1 | fn j |
| main.rs:850:5:850:6 | m6 | main.rs:116:1:128:1 | mod m6 |
| main.rs:850:5:850:9 | ...::g | main.rs:121:5:127:5 | fn g |
| main.rs:851:5:851:6 | m7 | main.rs:130:1:149:1 | mod m7 |
| main.rs:851:5:851:9 | ...::f | main.rs:141:5:148:5 | fn f |
| main.rs:852:5:852:6 | m8 | main.rs:151:1:205:1 | mod m8 |
| main.rs:852:5:852:9 | ...::g | main.rs:189:5:204:5 | fn g |
| main.rs:853:5:853:6 | m9 | main.rs:207:1:215:1 | mod m9 |
| main.rs:853:5:853:9 | ...::f | main.rs:210:5:214:5 | fn f |
| main.rs:854:5:854:7 | m11 | main.rs:238:1:275:1 | mod m11 |
| main.rs:854:5:854:10 | ...::f | main.rs:243:5:246:5 | fn f |
| main.rs:855:5:855:7 | m15 | main.rs:306:1:375:1 | mod m15 |
| main.rs:855:5:855:10 | ...::f | main.rs:362:5:374:5 | fn f |
| main.rs:856:5:856:7 | m16 | main.rs:377:1:469:1 | mod m16 |
| main.rs:856:5:856:10 | ...::f | main.rs:444:5:468:5 | fn f |
| main.rs:857:5:857:20 | trait_visibility | main.rs:471:1:521:1 | mod trait_visibility |
| main.rs:857:5:857:23 | ...::f | main.rs:498:5:520:5 | fn f |
| main.rs:858:5:858:7 | m17 | main.rs:523:1:553:1 | mod m17 |
| main.rs:858:5:858:10 | ...::f | main.rs:547:5:552:5 | fn f |
| main.rs:859:5:859:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
| main.rs:859:5:859:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
| main.rs:860:5:860:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
| main.rs:860:5:860:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
| main.rs:861:5:861:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 |
| main.rs:861:5:861:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
| main.rs:862:5:862:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| main.rs:863:5:863:12 | my_alias | main.rs:1:1:1:7 | mod my |
| main.rs:863:5:863:22 | ...::nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| main.rs:864:5:864:7 | m18 | main.rs:555:1:573:1 | mod m18 |
| main.rs:864:5:864:12 | ...::m19 | main.rs:560:5:572:5 | mod m19 |
| main.rs:864:5:864:17 | ...::m20 | main.rs:565:9:571:9 | mod m20 |
| main.rs:864:5:864:20 | ...::g | main.rs:566:13:570:13 | fn g |
| main.rs:865:5:865:7 | m23 | main.rs:602:1:627:1 | mod m23 |
| main.rs:865:5:865:10 | ...::f | main.rs:622:5:626:5 | fn f |
| main.rs:866:5:866:7 | m24 | main.rs:629:1:697:1 | mod m24 |
| main.rs:866:5:866:10 | ...::f | main.rs:683:5:696:5 | fn f |
| main.rs:867:5:867:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) |
| main.rs:867:5:867:11 | ...::h | main.rs:57:1:76:1 | fn h |
| main.rs:868:5:868:13 | z_changed | main.rs:702:1:702:9 | fn z_changed |
| main.rs:869:5:869:11 | AStruct | main.rs:704:1:704:17 | struct AStruct |
| main.rs:869:5:869:22 | ...::z_on_type | main.rs:708:5:708:17 | fn z_on_type |
| main.rs:870:5:870:11 | AStruct | main.rs:704:1:704:17 | struct AStruct |
| main.rs:871:5:871:29 | impl_with_attribute_macro | main.rs:772:1:791:1 | mod impl_with_attribute_macro |
| main.rs:871:5:871:35 | ...::test | main.rs:787:5:790:5 | fn test |
| main.rs:872:5:872:12 | patterns | main.rs:793:1:834:1 | mod patterns |
| main.rs:872:5:872:18 | ...::test | main.rs:794:5:808:5 | fn test |
| my2/mod.rs:4:5:4:11 | println | {EXTERNAL LOCATION} | MacroRules |
| my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
@@ -493,7 +514,7 @@ resolvePath
| my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g |
| my2/my3/mod.rs:4:5:4:5 | h | main.rs:57:1:76:1 | fn h |
| my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:25:34 | SourceFile |
| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:829:2 | SourceFile |
| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:873:2 | SourceFile |
| my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:57:1:76:1 | fn h |
| my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:25:34 | SourceFile |
| my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g |

View File

@@ -5,7 +5,7 @@ import TestUtils
query predicate mod(Module m) { toBeTested(m) }
query predicate resolvePath(Path p, ItemNode i) {
query predicate resolvePath(PathExt p, ItemNode i) {
toBeTested(p) and
not p.isFromMacroExpansion() and
i = resolvePath(p)

View File

@@ -1798,145 +1798,216 @@ edges
| main.rs:753:5:753:16 | print_i64(...) | main.rs:744:18:754:1 | { ... } | |
| main.rs:753:5:753:17 | ExprStmt | main.rs:753:5:753:13 | print_i64 | |
| main.rs:753:15:753:15 | x | main.rs:753:5:753:16 | print_i64(...) | |
| main.rs:756:1:800:1 | enter fn main | main.rs:757:5:757:25 | ExprStmt | |
| main.rs:756:1:800:1 | exit fn main (normal) | main.rs:756:1:800:1 | exit fn main | |
| main.rs:756:11:800:1 | { ... } | main.rs:756:1:800:1 | exit fn main (normal) | |
| main.rs:757:5:757:22 | immutable_variable | main.rs:757:5:757:24 | immutable_variable(...) | |
| main.rs:757:5:757:24 | immutable_variable(...) | main.rs:758:5:758:23 | ExprStmt | |
| main.rs:757:5:757:25 | ExprStmt | main.rs:757:5:757:22 | immutable_variable | |
| main.rs:758:5:758:20 | mutable_variable | main.rs:758:5:758:22 | mutable_variable(...) | |
| main.rs:758:5:758:22 | mutable_variable(...) | main.rs:759:5:759:40 | ExprStmt | |
| main.rs:758:5:758:23 | ExprStmt | main.rs:758:5:758:20 | mutable_variable | |
| main.rs:759:5:759:37 | mutable_variable_immutable_borrow | main.rs:759:5:759:39 | mutable_variable_immutable_borrow(...) | |
| main.rs:759:5:759:39 | mutable_variable_immutable_borrow(...) | main.rs:760:5:760:23 | ExprStmt | |
| main.rs:759:5:759:40 | ExprStmt | main.rs:759:5:759:37 | mutable_variable_immutable_borrow | |
| main.rs:760:5:760:20 | variable_shadow1 | main.rs:760:5:760:22 | variable_shadow1(...) | |
| main.rs:760:5:760:22 | variable_shadow1(...) | main.rs:761:5:761:23 | ExprStmt | |
| main.rs:760:5:760:23 | ExprStmt | main.rs:760:5:760:20 | variable_shadow1 | |
| main.rs:761:5:761:20 | variable_shadow2 | main.rs:761:5:761:22 | variable_shadow2(...) | |
| main.rs:761:5:761:22 | variable_shadow2(...) | main.rs:762:5:762:19 | ExprStmt | |
| main.rs:761:5:761:23 | ExprStmt | main.rs:761:5:761:20 | variable_shadow2 | |
| main.rs:762:5:762:16 | let_pattern1 | main.rs:762:5:762:18 | let_pattern1(...) | |
| main.rs:762:5:762:18 | let_pattern1(...) | main.rs:763:5:763:19 | ExprStmt | |
| main.rs:762:5:762:19 | ExprStmt | main.rs:762:5:762:16 | let_pattern1 | |
| main.rs:763:5:763:16 | let_pattern2 | main.rs:763:5:763:18 | let_pattern2(...) | |
| main.rs:763:5:763:18 | let_pattern2(...) | main.rs:764:5:764:19 | ExprStmt | |
| main.rs:763:5:763:19 | ExprStmt | main.rs:763:5:763:16 | let_pattern2 | |
| main.rs:764:5:764:16 | let_pattern3 | main.rs:764:5:764:18 | let_pattern3(...) | |
| main.rs:764:5:764:18 | let_pattern3(...) | main.rs:765:5:765:19 | ExprStmt | |
| main.rs:764:5:764:19 | ExprStmt | main.rs:764:5:764:16 | let_pattern3 | |
| main.rs:765:5:765:16 | let_pattern4 | main.rs:765:5:765:18 | let_pattern4(...) | |
| main.rs:765:5:765:18 | let_pattern4(...) | main.rs:766:5:766:21 | ExprStmt | |
| main.rs:765:5:765:19 | ExprStmt | main.rs:765:5:765:16 | let_pattern4 | |
| main.rs:766:5:766:18 | match_pattern1 | main.rs:766:5:766:20 | match_pattern1(...) | |
| main.rs:766:5:766:20 | match_pattern1(...) | main.rs:767:5:767:21 | ExprStmt | |
| main.rs:766:5:766:21 | ExprStmt | main.rs:766:5:766:18 | match_pattern1 | |
| main.rs:767:5:767:18 | match_pattern2 | main.rs:767:5:767:20 | match_pattern2(...) | |
| main.rs:767:5:767:20 | match_pattern2(...) | main.rs:768:5:768:21 | ExprStmt | |
| main.rs:767:5:767:21 | ExprStmt | main.rs:767:5:767:18 | match_pattern2 | |
| main.rs:768:5:768:18 | match_pattern3 | main.rs:768:5:768:20 | match_pattern3(...) | |
| main.rs:768:5:768:20 | match_pattern3(...) | main.rs:769:5:769:21 | ExprStmt | |
| main.rs:768:5:768:21 | ExprStmt | main.rs:768:5:768:18 | match_pattern3 | |
| main.rs:769:5:769:18 | match_pattern4 | main.rs:769:5:769:20 | match_pattern4(...) | |
| main.rs:769:5:769:20 | match_pattern4(...) | main.rs:770:5:770:21 | ExprStmt | |
| main.rs:769:5:769:21 | ExprStmt | main.rs:769:5:769:18 | match_pattern4 | |
| main.rs:770:5:770:18 | match_pattern5 | main.rs:770:5:770:20 | match_pattern5(...) | |
| main.rs:770:5:770:20 | match_pattern5(...) | main.rs:771:5:771:21 | ExprStmt | |
| main.rs:770:5:770:21 | ExprStmt | main.rs:770:5:770:18 | match_pattern5 | |
| main.rs:771:5:771:18 | match_pattern6 | main.rs:771:5:771:20 | match_pattern6(...) | |
| main.rs:771:5:771:20 | match_pattern6(...) | main.rs:772:5:772:21 | ExprStmt | |
| main.rs:771:5:771:21 | ExprStmt | main.rs:771:5:771:18 | match_pattern6 | |
| main.rs:772:5:772:18 | match_pattern7 | main.rs:772:5:772:20 | match_pattern7(...) | |
| main.rs:772:5:772:20 | match_pattern7(...) | main.rs:773:5:773:21 | ExprStmt | |
| main.rs:772:5:772:21 | ExprStmt | main.rs:772:5:772:18 | match_pattern7 | |
| main.rs:773:5:773:18 | match_pattern8 | main.rs:773:5:773:20 | match_pattern8(...) | |
| main.rs:773:5:773:20 | match_pattern8(...) | main.rs:774:5:774:21 | ExprStmt | |
| main.rs:773:5:773:21 | ExprStmt | main.rs:773:5:773:18 | match_pattern8 | |
| main.rs:774:5:774:18 | match_pattern9 | main.rs:774:5:774:20 | match_pattern9(...) | |
| main.rs:774:5:774:20 | match_pattern9(...) | main.rs:775:5:775:22 | ExprStmt | |
| main.rs:774:5:774:21 | ExprStmt | main.rs:774:5:774:18 | match_pattern9 | |
| main.rs:775:5:775:19 | match_pattern10 | main.rs:775:5:775:21 | match_pattern10(...) | |
| main.rs:775:5:775:21 | match_pattern10(...) | main.rs:776:5:776:22 | ExprStmt | |
| main.rs:775:5:775:22 | ExprStmt | main.rs:775:5:775:19 | match_pattern10 | |
| main.rs:776:5:776:19 | match_pattern11 | main.rs:776:5:776:21 | match_pattern11(...) | |
| main.rs:776:5:776:21 | match_pattern11(...) | main.rs:777:5:777:22 | ExprStmt | |
| main.rs:776:5:776:22 | ExprStmt | main.rs:776:5:776:19 | match_pattern11 | |
| main.rs:777:5:777:19 | match_pattern12 | main.rs:777:5:777:21 | match_pattern12(...) | |
| main.rs:777:5:777:21 | match_pattern12(...) | main.rs:778:5:778:22 | ExprStmt | |
| main.rs:777:5:777:22 | ExprStmt | main.rs:777:5:777:19 | match_pattern12 | |
| main.rs:778:5:778:19 | match_pattern13 | main.rs:778:5:778:21 | match_pattern13(...) | |
| main.rs:778:5:778:21 | match_pattern13(...) | main.rs:779:5:779:22 | ExprStmt | |
| main.rs:778:5:778:22 | ExprStmt | main.rs:778:5:778:19 | match_pattern13 | |
| main.rs:779:5:779:19 | match_pattern14 | main.rs:779:5:779:21 | match_pattern14(...) | |
| main.rs:779:5:779:21 | match_pattern14(...) | main.rs:780:5:780:22 | ExprStmt | |
| main.rs:779:5:779:22 | ExprStmt | main.rs:779:5:779:19 | match_pattern14 | |
| main.rs:780:5:780:19 | match_pattern15 | main.rs:780:5:780:21 | match_pattern15(...) | |
| main.rs:780:5:780:21 | match_pattern15(...) | main.rs:781:5:781:22 | ExprStmt | |
| main.rs:780:5:780:22 | ExprStmt | main.rs:780:5:780:19 | match_pattern15 | |
| main.rs:781:5:781:19 | match_pattern16 | main.rs:781:5:781:21 | match_pattern16(...) | |
| main.rs:781:5:781:21 | match_pattern16(...) | main.rs:782:5:782:36 | ExprStmt | |
| main.rs:781:5:781:22 | ExprStmt | main.rs:781:5:781:19 | match_pattern16 | |
| main.rs:782:5:782:18 | param_pattern1 | main.rs:782:20:782:22 | "a" | |
| main.rs:782:5:782:35 | param_pattern1(...) | main.rs:783:5:783:37 | ExprStmt | |
| main.rs:782:5:782:36 | ExprStmt | main.rs:782:5:782:18 | param_pattern1 | |
| main.rs:782:20:782:22 | "a" | main.rs:782:26:782:28 | "b" | |
| main.rs:782:25:782:34 | TupleExpr | main.rs:782:5:782:35 | param_pattern1(...) | |
| main.rs:782:26:782:28 | "b" | main.rs:782:31:782:33 | "c" | |
| main.rs:782:31:782:33 | "c" | main.rs:782:25:782:34 | TupleExpr | |
| main.rs:783:5:783:18 | param_pattern2 | main.rs:783:20:783:31 | ...::Left | |
| main.rs:783:5:783:36 | param_pattern2(...) | main.rs:784:5:784:26 | ExprStmt | |
| main.rs:783:5:783:37 | ExprStmt | main.rs:783:5:783:18 | param_pattern2 | |
| main.rs:783:20:783:31 | ...::Left | main.rs:783:33:783:34 | 45 | |
| main.rs:783:20:783:35 | ...::Left(...) | main.rs:783:5:783:36 | param_pattern2(...) | |
| main.rs:783:33:783:34 | 45 | main.rs:783:20:783:35 | ...::Left(...) | |
| main.rs:784:5:784:23 | destruct_assignment | main.rs:784:5:784:25 | destruct_assignment(...) | |
| main.rs:784:5:784:25 | destruct_assignment(...) | main.rs:785:5:785:23 | ExprStmt | |
| main.rs:784:5:784:26 | ExprStmt | main.rs:784:5:784:23 | destruct_assignment | |
| main.rs:785:5:785:20 | closure_variable | main.rs:785:5:785:22 | closure_variable(...) | |
| main.rs:785:5:785:22 | closure_variable(...) | main.rs:786:5:786:22 | ExprStmt | |
| main.rs:785:5:785:23 | ExprStmt | main.rs:785:5:785:20 | closure_variable | |
| main.rs:786:5:786:19 | nested_function | main.rs:786:5:786:21 | nested_function(...) | |
| main.rs:786:5:786:21 | nested_function(...) | main.rs:787:5:787:19 | ExprStmt | |
| main.rs:786:5:786:22 | ExprStmt | main.rs:786:5:786:19 | nested_function | |
| main.rs:787:5:787:16 | for_variable | main.rs:787:5:787:18 | for_variable(...) | |
| main.rs:787:5:787:18 | for_variable(...) | main.rs:788:5:788:17 | ExprStmt | |
| main.rs:787:5:787:19 | ExprStmt | main.rs:787:5:787:16 | for_variable | |
| main.rs:788:5:788:14 | add_assign | main.rs:788:5:788:16 | add_assign(...) | |
| main.rs:788:5:788:16 | add_assign(...) | main.rs:789:5:789:13 | ExprStmt | |
| main.rs:788:5:788:17 | ExprStmt | main.rs:788:5:788:14 | add_assign | |
| main.rs:789:5:789:10 | mutate | main.rs:789:5:789:12 | mutate(...) | |
| main.rs:789:5:789:12 | mutate(...) | main.rs:790:5:790:17 | ExprStmt | |
| main.rs:789:5:789:13 | ExprStmt | main.rs:789:5:789:10 | mutate | |
| main.rs:790:5:790:14 | mutate_arg | main.rs:790:5:790:16 | mutate_arg(...) | |
| main.rs:790:5:790:16 | mutate_arg(...) | main.rs:791:5:791:12 | ExprStmt | |
| main.rs:790:5:790:17 | ExprStmt | main.rs:790:5:790:14 | mutate_arg | |
| main.rs:791:5:791:9 | alias | main.rs:791:5:791:11 | alias(...) | |
| main.rs:791:5:791:11 | alias(...) | main.rs:792:5:792:18 | ExprStmt | |
| main.rs:791:5:791:12 | ExprStmt | main.rs:791:5:791:9 | alias | |
| main.rs:792:5:792:15 | capture_mut | main.rs:792:5:792:17 | capture_mut(...) | |
| main.rs:792:5:792:17 | capture_mut(...) | main.rs:793:5:793:20 | ExprStmt | |
| main.rs:792:5:792:18 | ExprStmt | main.rs:792:5:792:15 | capture_mut | |
| main.rs:793:5:793:17 | capture_immut | main.rs:793:5:793:19 | capture_immut(...) | |
| main.rs:793:5:793:19 | capture_immut(...) | main.rs:794:5:794:26 | ExprStmt | |
| main.rs:793:5:793:20 | ExprStmt | main.rs:793:5:793:17 | capture_immut | |
| main.rs:794:5:794:23 | async_block_capture | main.rs:794:5:794:25 | async_block_capture(...) | |
| main.rs:794:5:794:25 | async_block_capture(...) | main.rs:795:5:795:14 | ExprStmt | |
| main.rs:794:5:794:26 | ExprStmt | main.rs:794:5:794:23 | async_block_capture | |
| main.rs:795:5:795:11 | structs | main.rs:795:5:795:13 | structs(...) | |
| main.rs:795:5:795:13 | structs(...) | main.rs:796:5:796:14 | ExprStmt | |
| main.rs:795:5:795:14 | ExprStmt | main.rs:795:5:795:11 | structs | |
| main.rs:796:5:796:11 | ref_arg | main.rs:796:5:796:13 | ref_arg(...) | |
| main.rs:796:5:796:13 | ref_arg(...) | main.rs:797:5:797:30 | ExprStmt | |
| main.rs:796:5:796:14 | ExprStmt | main.rs:796:5:796:11 | ref_arg | |
| main.rs:797:5:797:27 | ref_methodcall_receiver | main.rs:797:5:797:29 | ref_methodcall_receiver(...) | |
| main.rs:797:5:797:29 | ref_methodcall_receiver(...) | main.rs:798:5:798:23 | ExprStmt | |
| main.rs:797:5:797:30 | ExprStmt | main.rs:797:5:797:27 | ref_methodcall_receiver | |
| main.rs:798:5:798:20 | macro_invocation | main.rs:798:5:798:22 | macro_invocation(...) | |
| main.rs:798:5:798:22 | macro_invocation(...) | main.rs:799:5:799:18 | ExprStmt | |
| main.rs:798:5:798:23 | ExprStmt | main.rs:798:5:798:20 | macro_invocation | |
| main.rs:799:5:799:15 | capture_phi | main.rs:799:5:799:17 | capture_phi(...) | |
| main.rs:799:5:799:17 | capture_phi(...) | main.rs:756:11:800:1 | { ... } | |
| main.rs:799:5:799:18 | ExprStmt | main.rs:799:5:799:15 | capture_phi | |
| main.rs:757:5:772:5 | enter fn test | main.rs:759:9:759:25 | let ... = ... | |
| main.rs:757:5:772:5 | exit fn test (normal) | main.rs:757:5:772:5 | exit fn test | |
| main.rs:758:34:772:5 | { ... } | main.rs:757:5:772:5 | exit fn test (normal) | |
| main.rs:759:9:759:25 | let ... = ... | main.rs:759:17:759:20 | Some | |
| main.rs:759:13:759:13 | x | main.rs:759:13:759:13 | x | |
| main.rs:759:13:759:13 | x | main.rs:760:9:767:10 | let ... = ... | match |
| main.rs:759:17:759:20 | Some | main.rs:759:22:759:23 | 42 | |
| main.rs:759:17:759:24 | Some(...) | main.rs:759:13:759:13 | x | |
| main.rs:759:22:759:23 | 42 | main.rs:759:17:759:24 | Some(...) | |
| main.rs:760:9:767:10 | let ... = ... | main.rs:761:19:761:19 | x | |
| main.rs:760:13:760:13 | y | main.rs:760:13:760:13 | y | |
| main.rs:760:13:760:13 | y | main.rs:768:15:768:15 | y | match |
| main.rs:761:13:767:9 | match x { ... } | main.rs:760:13:760:13 | y | |
| main.rs:761:19:761:19 | x | main.rs:762:13:762:19 | Some(...) | |
| main.rs:762:13:762:19 | Some(...) | main.rs:762:18:762:18 | y | match |
| main.rs:762:13:762:19 | Some(...) | main.rs:765:13:765:16 | None | no-match |
| main.rs:762:18:762:18 | y | main.rs:762:18:762:18 | y | |
| main.rs:762:18:762:18 | y | main.rs:763:17:763:20 | None | match |
| main.rs:762:24:764:13 | { ... } | main.rs:761:13:767:9 | match x { ... } | |
| main.rs:763:17:763:20 | None | main.rs:762:24:764:13 | { ... } | |
| main.rs:765:13:765:16 | None | main.rs:765:13:765:16 | None | |
| main.rs:765:13:765:16 | None | main.rs:766:17:766:20 | None | match |
| main.rs:766:17:766:20 | None | main.rs:761:13:767:9 | match x { ... } | |
| main.rs:768:9:771:9 | match y { ... } | main.rs:758:34:772:5 | { ... } | |
| main.rs:768:15:768:15 | y | main.rs:769:13:769:16 | N0ne | |
| main.rs:769:13:769:16 | N0ne | main.rs:769:13:769:16 | N0ne | |
| main.rs:769:13:769:16 | N0ne | main.rs:770:17:770:20 | N0ne | match |
| main.rs:770:17:770:20 | N0ne | main.rs:768:9:771:9 | match y { ... } | |
| main.rs:774:5:781:5 | enter fn test2 | main.rs:776:9:777:17 | let ... = test | |
| main.rs:774:5:781:5 | exit fn test2 (normal) | main.rs:774:5:781:5 | exit fn test2 | |
| main.rs:775:31:781:5 | { ... } | main.rs:774:5:781:5 | exit fn test2 (normal) | |
| main.rs:776:9:777:17 | let ... = test | main.rs:777:13:777:16 | test | |
| main.rs:776:13:776:22 | test_alias | main.rs:776:13:776:22 | test_alias | |
| main.rs:776:13:776:22 | test_alias | main.rs:778:9:779:25 | let ... = ... | match |
| main.rs:777:13:777:16 | test | main.rs:776:13:776:22 | test_alias | |
| main.rs:778:9:779:25 | let ... = ... | main.rs:779:13:779:22 | test_alias | |
| main.rs:778:13:778:16 | test | main.rs:778:13:778:16 | test | |
| main.rs:778:13:778:16 | test | main.rs:780:9:780:12 | test | match |
| main.rs:779:13:779:22 | test_alias | main.rs:779:13:779:24 | test_alias(...) | |
| main.rs:779:13:779:24 | test_alias(...) | main.rs:778:13:778:16 | test | |
| main.rs:780:9:780:12 | test | main.rs:775:31:781:5 | { ... } | |
| main.rs:785:5:798:5 | enter fn test3 | main.rs:787:9:787:24 | let ... = ... | |
| main.rs:785:5:798:5 | exit fn test3 (normal) | main.rs:785:5:798:5 | exit fn test3 | |
| main.rs:786:16:798:5 | { ... } | main.rs:785:5:798:5 | exit fn test3 (normal) | |
| main.rs:787:9:787:24 | let ... = ... | main.rs:787:17:787:20 | Some | |
| main.rs:787:13:787:13 | x | main.rs:787:13:787:13 | x | |
| main.rs:787:13:787:13 | x | main.rs:788:9:792:10 | ExprStmt | match |
| main.rs:787:17:787:20 | Some | main.rs:787:22:787:22 | 0 | |
| main.rs:787:17:787:23 | Some(...) | main.rs:787:13:787:13 | x | |
| main.rs:787:22:787:22 | 0 | main.rs:787:17:787:23 | Some(...) | |
| main.rs:788:9:792:9 | match x { ... } | main.rs:793:9:797:10 | ExprStmt | |
| main.rs:788:9:792:10 | ExprStmt | main.rs:788:15:788:15 | x | |
| main.rs:788:15:788:15 | x | main.rs:789:13:789:19 | Some(...) | |
| main.rs:789:13:789:19 | Some(...) | main.rs:789:18:789:18 | x | match |
| main.rs:789:13:789:19 | Some(...) | main.rs:791:13:791:13 | _ | no-match |
| main.rs:789:18:789:18 | x | main.rs:789:18:789:18 | x | |
| main.rs:789:18:789:18 | x | main.rs:790:20:790:20 | x | match |
| main.rs:790:20:790:20 | x | main.rs:788:9:792:9 | match x { ... } | |
| main.rs:791:13:791:13 | _ | main.rs:791:18:791:18 | 0 | match |
| main.rs:791:18:791:18 | 0 | main.rs:788:9:792:9 | match x { ... } | |
| main.rs:793:9:797:9 | match x { ... } | main.rs:786:16:798:5 | { ... } | |
| main.rs:793:9:797:10 | ExprStmt | main.rs:793:15:793:15 | x | |
| main.rs:793:15:793:15 | x | main.rs:794:13:794:19 | Some(...) | |
| main.rs:794:13:794:19 | Some(...) | main.rs:794:18:794:18 | z | match |
| main.rs:794:13:794:19 | Some(...) | main.rs:796:13:796:13 | _ | no-match |
| main.rs:794:18:794:18 | z | main.rs:794:18:794:18 | z | |
| main.rs:794:18:794:18 | z | main.rs:795:17:795:17 | z | match |
| main.rs:794:18:794:18 | z | main.rs:796:13:796:13 | _ | no-match |
| main.rs:795:17:795:17 | z | main.rs:793:9:797:9 | match x { ... } | |
| main.rs:796:13:796:13 | _ | main.rs:796:18:796:18 | 0 | match |
| main.rs:796:18:796:18 | 0 | main.rs:793:9:797:9 | match x { ... } | |
| main.rs:801:1:845:1 | enter fn main | main.rs:802:5:802:25 | ExprStmt | |
| main.rs:801:1:845:1 | exit fn main (normal) | main.rs:801:1:845:1 | exit fn main | |
| main.rs:801:11:845:1 | { ... } | main.rs:801:1:845:1 | exit fn main (normal) | |
| main.rs:802:5:802:22 | immutable_variable | main.rs:802:5:802:24 | immutable_variable(...) | |
| main.rs:802:5:802:24 | immutable_variable(...) | main.rs:803:5:803:23 | ExprStmt | |
| main.rs:802:5:802:25 | ExprStmt | main.rs:802:5:802:22 | immutable_variable | |
| main.rs:803:5:803:20 | mutable_variable | main.rs:803:5:803:22 | mutable_variable(...) | |
| main.rs:803:5:803:22 | mutable_variable(...) | main.rs:804:5:804:40 | ExprStmt | |
| main.rs:803:5:803:23 | ExprStmt | main.rs:803:5:803:20 | mutable_variable | |
| main.rs:804:5:804:37 | mutable_variable_immutable_borrow | main.rs:804:5:804:39 | mutable_variable_immutable_borrow(...) | |
| main.rs:804:5:804:39 | mutable_variable_immutable_borrow(...) | main.rs:805:5:805:23 | ExprStmt | |
| main.rs:804:5:804:40 | ExprStmt | main.rs:804:5:804:37 | mutable_variable_immutable_borrow | |
| main.rs:805:5:805:20 | variable_shadow1 | main.rs:805:5:805:22 | variable_shadow1(...) | |
| main.rs:805:5:805:22 | variable_shadow1(...) | main.rs:806:5:806:23 | ExprStmt | |
| main.rs:805:5:805:23 | ExprStmt | main.rs:805:5:805:20 | variable_shadow1 | |
| main.rs:806:5:806:20 | variable_shadow2 | main.rs:806:5:806:22 | variable_shadow2(...) | |
| main.rs:806:5:806:22 | variable_shadow2(...) | main.rs:807:5:807:19 | ExprStmt | |
| main.rs:806:5:806:23 | ExprStmt | main.rs:806:5:806:20 | variable_shadow2 | |
| main.rs:807:5:807:16 | let_pattern1 | main.rs:807:5:807:18 | let_pattern1(...) | |
| main.rs:807:5:807:18 | let_pattern1(...) | main.rs:808:5:808:19 | ExprStmt | |
| main.rs:807:5:807:19 | ExprStmt | main.rs:807:5:807:16 | let_pattern1 | |
| main.rs:808:5:808:16 | let_pattern2 | main.rs:808:5:808:18 | let_pattern2(...) | |
| main.rs:808:5:808:18 | let_pattern2(...) | main.rs:809:5:809:19 | ExprStmt | |
| main.rs:808:5:808:19 | ExprStmt | main.rs:808:5:808:16 | let_pattern2 | |
| main.rs:809:5:809:16 | let_pattern3 | main.rs:809:5:809:18 | let_pattern3(...) | |
| main.rs:809:5:809:18 | let_pattern3(...) | main.rs:810:5:810:19 | ExprStmt | |
| main.rs:809:5:809:19 | ExprStmt | main.rs:809:5:809:16 | let_pattern3 | |
| main.rs:810:5:810:16 | let_pattern4 | main.rs:810:5:810:18 | let_pattern4(...) | |
| main.rs:810:5:810:18 | let_pattern4(...) | main.rs:811:5:811:21 | ExprStmt | |
| main.rs:810:5:810:19 | ExprStmt | main.rs:810:5:810:16 | let_pattern4 | |
| main.rs:811:5:811:18 | match_pattern1 | main.rs:811:5:811:20 | match_pattern1(...) | |
| main.rs:811:5:811:20 | match_pattern1(...) | main.rs:812:5:812:21 | ExprStmt | |
| main.rs:811:5:811:21 | ExprStmt | main.rs:811:5:811:18 | match_pattern1 | |
| main.rs:812:5:812:18 | match_pattern2 | main.rs:812:5:812:20 | match_pattern2(...) | |
| main.rs:812:5:812:20 | match_pattern2(...) | main.rs:813:5:813:21 | ExprStmt | |
| main.rs:812:5:812:21 | ExprStmt | main.rs:812:5:812:18 | match_pattern2 | |
| main.rs:813:5:813:18 | match_pattern3 | main.rs:813:5:813:20 | match_pattern3(...) | |
| main.rs:813:5:813:20 | match_pattern3(...) | main.rs:814:5:814:21 | ExprStmt | |
| main.rs:813:5:813:21 | ExprStmt | main.rs:813:5:813:18 | match_pattern3 | |
| main.rs:814:5:814:18 | match_pattern4 | main.rs:814:5:814:20 | match_pattern4(...) | |
| main.rs:814:5:814:20 | match_pattern4(...) | main.rs:815:5:815:21 | ExprStmt | |
| main.rs:814:5:814:21 | ExprStmt | main.rs:814:5:814:18 | match_pattern4 | |
| main.rs:815:5:815:18 | match_pattern5 | main.rs:815:5:815:20 | match_pattern5(...) | |
| main.rs:815:5:815:20 | match_pattern5(...) | main.rs:816:5:816:21 | ExprStmt | |
| main.rs:815:5:815:21 | ExprStmt | main.rs:815:5:815:18 | match_pattern5 | |
| main.rs:816:5:816:18 | match_pattern6 | main.rs:816:5:816:20 | match_pattern6(...) | |
| main.rs:816:5:816:20 | match_pattern6(...) | main.rs:817:5:817:21 | ExprStmt | |
| main.rs:816:5:816:21 | ExprStmt | main.rs:816:5:816:18 | match_pattern6 | |
| main.rs:817:5:817:18 | match_pattern7 | main.rs:817:5:817:20 | match_pattern7(...) | |
| main.rs:817:5:817:20 | match_pattern7(...) | main.rs:818:5:818:21 | ExprStmt | |
| main.rs:817:5:817:21 | ExprStmt | main.rs:817:5:817:18 | match_pattern7 | |
| main.rs:818:5:818:18 | match_pattern8 | main.rs:818:5:818:20 | match_pattern8(...) | |
| main.rs:818:5:818:20 | match_pattern8(...) | main.rs:819:5:819:21 | ExprStmt | |
| main.rs:818:5:818:21 | ExprStmt | main.rs:818:5:818:18 | match_pattern8 | |
| main.rs:819:5:819:18 | match_pattern9 | main.rs:819:5:819:20 | match_pattern9(...) | |
| main.rs:819:5:819:20 | match_pattern9(...) | main.rs:820:5:820:22 | ExprStmt | |
| main.rs:819:5:819:21 | ExprStmt | main.rs:819:5:819:18 | match_pattern9 | |
| main.rs:820:5:820:19 | match_pattern10 | main.rs:820:5:820:21 | match_pattern10(...) | |
| main.rs:820:5:820:21 | match_pattern10(...) | main.rs:821:5:821:22 | ExprStmt | |
| main.rs:820:5:820:22 | ExprStmt | main.rs:820:5:820:19 | match_pattern10 | |
| main.rs:821:5:821:19 | match_pattern11 | main.rs:821:5:821:21 | match_pattern11(...) | |
| main.rs:821:5:821:21 | match_pattern11(...) | main.rs:822:5:822:22 | ExprStmt | |
| main.rs:821:5:821:22 | ExprStmt | main.rs:821:5:821:19 | match_pattern11 | |
| main.rs:822:5:822:19 | match_pattern12 | main.rs:822:5:822:21 | match_pattern12(...) | |
| main.rs:822:5:822:21 | match_pattern12(...) | main.rs:823:5:823:22 | ExprStmt | |
| main.rs:822:5:822:22 | ExprStmt | main.rs:822:5:822:19 | match_pattern12 | |
| main.rs:823:5:823:19 | match_pattern13 | main.rs:823:5:823:21 | match_pattern13(...) | |
| main.rs:823:5:823:21 | match_pattern13(...) | main.rs:824:5:824:22 | ExprStmt | |
| main.rs:823:5:823:22 | ExprStmt | main.rs:823:5:823:19 | match_pattern13 | |
| main.rs:824:5:824:19 | match_pattern14 | main.rs:824:5:824:21 | match_pattern14(...) | |
| main.rs:824:5:824:21 | match_pattern14(...) | main.rs:825:5:825:22 | ExprStmt | |
| main.rs:824:5:824:22 | ExprStmt | main.rs:824:5:824:19 | match_pattern14 | |
| main.rs:825:5:825:19 | match_pattern15 | main.rs:825:5:825:21 | match_pattern15(...) | |
| main.rs:825:5:825:21 | match_pattern15(...) | main.rs:826:5:826:22 | ExprStmt | |
| main.rs:825:5:825:22 | ExprStmt | main.rs:825:5:825:19 | match_pattern15 | |
| main.rs:826:5:826:19 | match_pattern16 | main.rs:826:5:826:21 | match_pattern16(...) | |
| main.rs:826:5:826:21 | match_pattern16(...) | main.rs:827:5:827:36 | ExprStmt | |
| main.rs:826:5:826:22 | ExprStmt | main.rs:826:5:826:19 | match_pattern16 | |
| main.rs:827:5:827:18 | param_pattern1 | main.rs:827:20:827:22 | "a" | |
| main.rs:827:5:827:35 | param_pattern1(...) | main.rs:828:5:828:37 | ExprStmt | |
| main.rs:827:5:827:36 | ExprStmt | main.rs:827:5:827:18 | param_pattern1 | |
| main.rs:827:20:827:22 | "a" | main.rs:827:26:827:28 | "b" | |
| main.rs:827:25:827:34 | TupleExpr | main.rs:827:5:827:35 | param_pattern1(...) | |
| main.rs:827:26:827:28 | "b" | main.rs:827:31:827:33 | "c" | |
| main.rs:827:31:827:33 | "c" | main.rs:827:25:827:34 | TupleExpr | |
| main.rs:828:5:828:18 | param_pattern2 | main.rs:828:20:828:31 | ...::Left | |
| main.rs:828:5:828:36 | param_pattern2(...) | main.rs:829:5:829:26 | ExprStmt | |
| main.rs:828:5:828:37 | ExprStmt | main.rs:828:5:828:18 | param_pattern2 | |
| main.rs:828:20:828:31 | ...::Left | main.rs:828:33:828:34 | 45 | |
| main.rs:828:20:828:35 | ...::Left(...) | main.rs:828:5:828:36 | param_pattern2(...) | |
| main.rs:828:33:828:34 | 45 | main.rs:828:20:828:35 | ...::Left(...) | |
| main.rs:829:5:829:23 | destruct_assignment | main.rs:829:5:829:25 | destruct_assignment(...) | |
| main.rs:829:5:829:25 | destruct_assignment(...) | main.rs:830:5:830:23 | ExprStmt | |
| main.rs:829:5:829:26 | ExprStmt | main.rs:829:5:829:23 | destruct_assignment | |
| main.rs:830:5:830:20 | closure_variable | main.rs:830:5:830:22 | closure_variable(...) | |
| main.rs:830:5:830:22 | closure_variable(...) | main.rs:831:5:831:22 | ExprStmt | |
| main.rs:830:5:830:23 | ExprStmt | main.rs:830:5:830:20 | closure_variable | |
| main.rs:831:5:831:19 | nested_function | main.rs:831:5:831:21 | nested_function(...) | |
| main.rs:831:5:831:21 | nested_function(...) | main.rs:832:5:832:19 | ExprStmt | |
| main.rs:831:5:831:22 | ExprStmt | main.rs:831:5:831:19 | nested_function | |
| main.rs:832:5:832:16 | for_variable | main.rs:832:5:832:18 | for_variable(...) | |
| main.rs:832:5:832:18 | for_variable(...) | main.rs:833:5:833:17 | ExprStmt | |
| main.rs:832:5:832:19 | ExprStmt | main.rs:832:5:832:16 | for_variable | |
| main.rs:833:5:833:14 | add_assign | main.rs:833:5:833:16 | add_assign(...) | |
| main.rs:833:5:833:16 | add_assign(...) | main.rs:834:5:834:13 | ExprStmt | |
| main.rs:833:5:833:17 | ExprStmt | main.rs:833:5:833:14 | add_assign | |
| main.rs:834:5:834:10 | mutate | main.rs:834:5:834:12 | mutate(...) | |
| main.rs:834:5:834:12 | mutate(...) | main.rs:835:5:835:17 | ExprStmt | |
| main.rs:834:5:834:13 | ExprStmt | main.rs:834:5:834:10 | mutate | |
| main.rs:835:5:835:14 | mutate_arg | main.rs:835:5:835:16 | mutate_arg(...) | |
| main.rs:835:5:835:16 | mutate_arg(...) | main.rs:836:5:836:12 | ExprStmt | |
| main.rs:835:5:835:17 | ExprStmt | main.rs:835:5:835:14 | mutate_arg | |
| main.rs:836:5:836:9 | alias | main.rs:836:5:836:11 | alias(...) | |
| main.rs:836:5:836:11 | alias(...) | main.rs:837:5:837:18 | ExprStmt | |
| main.rs:836:5:836:12 | ExprStmt | main.rs:836:5:836:9 | alias | |
| main.rs:837:5:837:15 | capture_mut | main.rs:837:5:837:17 | capture_mut(...) | |
| main.rs:837:5:837:17 | capture_mut(...) | main.rs:838:5:838:20 | ExprStmt | |
| main.rs:837:5:837:18 | ExprStmt | main.rs:837:5:837:15 | capture_mut | |
| main.rs:838:5:838:17 | capture_immut | main.rs:838:5:838:19 | capture_immut(...) | |
| main.rs:838:5:838:19 | capture_immut(...) | main.rs:839:5:839:26 | ExprStmt | |
| main.rs:838:5:838:20 | ExprStmt | main.rs:838:5:838:17 | capture_immut | |
| main.rs:839:5:839:23 | async_block_capture | main.rs:839:5:839:25 | async_block_capture(...) | |
| main.rs:839:5:839:25 | async_block_capture(...) | main.rs:840:5:840:14 | ExprStmt | |
| main.rs:839:5:839:26 | ExprStmt | main.rs:839:5:839:23 | async_block_capture | |
| main.rs:840:5:840:11 | structs | main.rs:840:5:840:13 | structs(...) | |
| main.rs:840:5:840:13 | structs(...) | main.rs:841:5:841:14 | ExprStmt | |
| main.rs:840:5:840:14 | ExprStmt | main.rs:840:5:840:11 | structs | |
| main.rs:841:5:841:11 | ref_arg | main.rs:841:5:841:13 | ref_arg(...) | |
| main.rs:841:5:841:13 | ref_arg(...) | main.rs:842:5:842:30 | ExprStmt | |
| main.rs:841:5:841:14 | ExprStmt | main.rs:841:5:841:11 | ref_arg | |
| main.rs:842:5:842:27 | ref_methodcall_receiver | main.rs:842:5:842:29 | ref_methodcall_receiver(...) | |
| main.rs:842:5:842:29 | ref_methodcall_receiver(...) | main.rs:843:5:843:23 | ExprStmt | |
| main.rs:842:5:842:30 | ExprStmt | main.rs:842:5:842:27 | ref_methodcall_receiver | |
| main.rs:843:5:843:20 | macro_invocation | main.rs:843:5:843:22 | macro_invocation(...) | |
| main.rs:843:5:843:22 | macro_invocation(...) | main.rs:844:5:844:18 | ExprStmt | |
| main.rs:843:5:843:23 | ExprStmt | main.rs:843:5:843:20 | macro_invocation | |
| main.rs:844:5:844:15 | capture_phi | main.rs:844:5:844:17 | capture_phi(...) | |
| main.rs:844:5:844:17 | capture_phi(...) | main.rs:801:11:845:1 | { ... } | |
| main.rs:844:5:844:18 | ExprStmt | main.rs:844:5:844:15 | capture_phi | |
breakTarget
| main.rs:326:9:326:13 | break | main.rs:317:5:327:5 | while ... { ... } |
continueTarget

View File

@@ -196,6 +196,13 @@ definition
| main.rs:748:17:750:9 | SSA phi(x) | main.rs:745:13:745:13 | x |
| main.rs:749:13:749:13 | x | main.rs:745:13:745:13 | x |
| main.rs:752:5:752:13 | <captured exit> x | main.rs:745:13:745:13 | x |
| main.rs:759:13:759:13 | x | main.rs:759:13:759:13 | x |
| main.rs:760:13:760:13 | y | main.rs:760:13:760:13 | y |
| main.rs:769:13:769:16 | N0ne | main.rs:769:13:769:16 | N0ne |
| main.rs:776:13:776:22 | test_alias | main.rs:776:13:776:22 | test_alias |
| main.rs:778:13:778:16 | test | main.rs:778:13:778:16 | test |
| main.rs:787:13:787:13 | x | main.rs:787:13:787:13 | x |
| main.rs:789:18:789:18 | x | main.rs:789:18:789:18 | x |
read
| main.rs:5:14:5:14 | s | main.rs:5:14:5:14 | s | main.rs:7:20:7:20 | s |
| main.rs:10:14:10:14 | i | main.rs:10:14:10:14 | i | main.rs:12:20:12:20 | i |
@@ -404,6 +411,14 @@ read
| main.rs:746:13:746:15 | cap | main.rs:746:13:746:15 | cap | main.rs:752:5:752:7 | cap |
| main.rs:746:20:746:20 | b | main.rs:746:20:746:20 | b | main.rs:748:20:748:20 | b |
| main.rs:752:5:752:13 | <captured exit> x | main.rs:745:13:745:13 | x | main.rs:753:15:753:15 | x |
| main.rs:759:13:759:13 | x | main.rs:759:13:759:13 | x | main.rs:761:19:761:19 | x |
| main.rs:760:13:760:13 | y | main.rs:760:13:760:13 | y | main.rs:768:15:768:15 | y |
| main.rs:769:13:769:16 | N0ne | main.rs:769:13:769:16 | N0ne | main.rs:770:17:770:20 | N0ne |
| main.rs:776:13:776:22 | test_alias | main.rs:776:13:776:22 | test_alias | main.rs:779:13:779:22 | test_alias |
| main.rs:778:13:778:16 | test | main.rs:778:13:778:16 | test | main.rs:780:9:780:12 | test |
| main.rs:787:13:787:13 | x | main.rs:787:13:787:13 | x | main.rs:788:15:788:15 | x |
| main.rs:787:13:787:13 | x | main.rs:787:13:787:13 | x | main.rs:793:15:793:15 | x |
| main.rs:789:18:789:18 | x | main.rs:789:18:789:18 | x | main.rs:790:20:790:20 | x |
firstRead
| main.rs:5:14:5:14 | s | main.rs:5:14:5:14 | s | main.rs:7:20:7:20 | s |
| main.rs:10:14:10:14 | i | main.rs:10:14:10:14 | i | main.rs:12:20:12:20 | i |
@@ -570,6 +585,13 @@ firstRead
| main.rs:746:13:746:15 | cap | main.rs:746:13:746:15 | cap | main.rs:752:5:752:7 | cap |
| main.rs:746:20:746:20 | b | main.rs:746:20:746:20 | b | main.rs:748:20:748:20 | b |
| main.rs:752:5:752:13 | <captured exit> x | main.rs:745:13:745:13 | x | main.rs:753:15:753:15 | x |
| main.rs:759:13:759:13 | x | main.rs:759:13:759:13 | x | main.rs:761:19:761:19 | x |
| main.rs:760:13:760:13 | y | main.rs:760:13:760:13 | y | main.rs:768:15:768:15 | y |
| main.rs:769:13:769:16 | N0ne | main.rs:769:13:769:16 | N0ne | main.rs:770:17:770:20 | N0ne |
| main.rs:776:13:776:22 | test_alias | main.rs:776:13:776:22 | test_alias | main.rs:779:13:779:22 | test_alias |
| main.rs:778:13:778:16 | test | main.rs:778:13:778:16 | test | main.rs:780:9:780:12 | test |
| main.rs:787:13:787:13 | x | main.rs:787:13:787:13 | x | main.rs:788:15:788:15 | x |
| main.rs:789:18:789:18 | x | main.rs:789:18:789:18 | x | main.rs:790:20:790:20 | x |
adjacentReads
| main.rs:27:5:27:6 | x2 | main.rs:25:13:25:14 | x2 | main.rs:28:15:28:16 | x2 | main.rs:29:10:29:11 | x2 |
| main.rs:41:9:41:10 | x3 | main.rs:41:9:41:10 | x3 | main.rs:42:15:42:16 | x3 | main.rs:44:9:44:10 | x3 |
@@ -616,6 +638,7 @@ adjacentReads
| main.rs:676:13:676:13 | a | main.rs:676:13:676:13 | a | main.rs:677:15:677:15 | a | main.rs:678:5:678:5 | a |
| main.rs:676:13:676:13 | a | main.rs:676:13:676:13 | a | main.rs:678:5:678:5 | a | main.rs:679:15:679:15 | a |
| main.rs:685:9:685:9 | x | main.rs:685:9:685:9 | x | main.rs:686:20:686:20 | x | main.rs:687:15:687:15 | x |
| main.rs:787:13:787:13 | x | main.rs:787:13:787:13 | x | main.rs:788:15:788:15 | x | main.rs:793:15:793:15 | x |
phi
| main.rs:210:9:210:44 | SSA phi(a3) | main.rs:210:9:210:44 | a3 | main.rs:210:22:210:23 | a3 |
| main.rs:210:9:210:44 | SSA phi(a3) | main.rs:210:9:210:44 | a3 | main.rs:210:42:210:43 | a3 |
@@ -773,3 +796,8 @@ assigns
| main.rs:745:13:745:13 | x | main.rs:745:17:745:19 | 100 |
| main.rs:746:13:746:15 | cap | main.rs:746:19:751:5 | \|...\| ... |
| main.rs:749:13:749:13 | x | main.rs:749:17:749:19 | 200 |
| main.rs:759:13:759:13 | x | main.rs:759:17:759:24 | Some(...) |
| main.rs:760:13:760:13 | y | main.rs:761:13:767:9 | match x { ... } |
| main.rs:776:13:776:22 | test_alias | main.rs:777:13:777:16 | test |
| main.rs:778:13:778:16 | test | main.rs:779:13:779:24 | test_alias(...) |
| main.rs:787:13:787:13 | x | main.rs:787:17:787:23 | Some(...) |

View File

@@ -753,6 +753,51 @@ fn capture_phi() {
print_i64(x); // $ read_access=x
}
mod patterns {
#[rustfmt::skip]
pub fn test() -> Option<i32> {
let x = Some(42); // x
let y : Option<i32> = // y1
match x { // $ read_access=x
Some(y) => { // y2
None
}
None =>
None
};
match y { // $ read_access=y1
N0ne => // n0ne
N0ne // $ read_access=n0ne
}
}
#[rustfmt::skip]
fn test2() -> Option<i32> {
let test_alias = // test_alias
test;
let test = // test
test_alias(); // $ read_access=test_alias
test // $ read_access=test
}
const z: i32 = 0;
#[rustfmt::skip]
fn test3() {
let x = Some(0); // x1
match x { // $ read_access=x1
Some(x) // x2
=> x, // $ read_access=x2
_ => 0
};
match x { // $ read_access=x1
Some(z) =>
z,
_ => 0
};
}
}
fn main() {
immutable_variable();
mutable_variable();

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