-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Unified: Basic data flow and clear-text logging query #22560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
f6bd6e8
unified: Add ExprPositions
asgerf ed87152
unified: Scaffold empty data flow graph with test
asgerf a35466d
unified: Add taint through +
asgerf 75d215d
unified: Add basic test with tuples
asgerf a1bca71
unified: Add steps for member access and tuples
asgerf eadbcd1
unified: Add query for viewing data flow graph
asgerf e8ee131
unified: Add incoming-value nodes
asgerf a87414c
unified: CFG-insensitive variable flow
asgerf dfd1a50
unified: Add post-update nodes
asgerf 707238e
unified: Add variable-ref nodes
asgerf b5c2ff6
unified: Update debug graph
asgerf d0e5d1b
unified: Add LocalSsa
asgerf e5efdbd
unified: Include SSA steps in debug view
asgerf bf3aae6
unified: Handle implicit 'self' references
asgerf ff8e042
unified: Add some tests with assignment-timing
asgerf 098e7e0
unified: Instantiate DataFlowConsistency
asgerf 09cfe5d
unified: Add flow through string interpolation
asgerf a03cd48
unified: Add dumb version of CleartextLogging
asgerf 2d1a99c
unified: Copy query help from old swift
asgerf 02564e9
Add support for AssociatedTypeDeclaration return type
asgerf 3c332a3
Update unified/ql/src/queries/security/CWE-312/CleartextLogging.qhelp
asgerf 0b48cd4
unified: Add plugin
asgerf 2acd6da
unified: Add local SSA consistency-query
asgerf 6fe1db0
unified: Add sink calls without flow
asgerf dea3219
unified: Explain the "local" in "local SSA"
asgerf 5f2b8e8
unified: Rename to TExprPostUpdateNode for clarity
asgerf 535b215
unified: Fill in nodeIsVisible and neverSkipInPathGraph
asgerf 6f0f14a
unified: Include path problem output tuples
asgerf 11bcf84
unified: Omit "unit" type from path steps
asgerf 343459c
unified: Update expected output
asgerf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| private import unified | ||
| private import codeql.unified.internal.dataflow.AllDataFlow | ||
| private import codeql.dataflow.internal.DataFlowImplConsistency | ||
|
|
||
| module ConsistencyInput implements InputSig<Location, DataFlowInput> { } | ||
|
|
||
| module ConsistencyOutput = | ||
| MakeConsistency<Location, DataFlowInput, TaintTrackingInput, ConsistencyInput>; | ||
|
|
||
| import ConsistencyOutput | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| private import unified | ||
| private import codeql.unified.internal.dataflow.LocalSsa | ||
| import LocalSsaOutput::Consistency |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| private import unified | ||
| private import NameBinding as NameBinding | ||
|
|
||
| /** | ||
| * Holds if `expr` appears in the context of a type annotation. | ||
| */ | ||
| predicate isInTypeContext(Expr expr) { | ||
| expr = any(TypeCastExpr n).getType() | ||
| or | ||
| expr = any(TypeTestExpr n).getType() | ||
| or | ||
| expr = any(VariableDeclaration n).getType() | ||
| or | ||
| expr = any(FunctionDeclaration n).getReturnType() | ||
| or | ||
| expr = any(FunctionExpr n).getReturnType() | ||
| or | ||
| expr = any(AccessorDeclaration n).getType() | ||
| or | ||
| expr = any(Parameter n).getType() | ||
| or | ||
| expr = any(TypeAliasDeclaration n).getType() | ||
| or | ||
| expr = any(BaseType n).getType() | ||
| or | ||
| expr = any(TypeParameter n).getBound() | ||
| or | ||
| expr = any(AssociatedTypeDeclaration n).getBound() | ||
| or | ||
| expr.getParent() instanceof TypeConstraint | ||
| or | ||
| isInTypeContext(expr.getEnclosingExpr()) | ||
| } | ||
|
|
||
| /** Holds if `e` appears in a name-binding position inside `declaration` */ | ||
| predicate isInBindingContext(Expr e, AstNode declaration) { | ||
| NameBinding::bindingContext(e, _, declaration) | ||
| } | ||
|
|
||
| /** Holds if `e` is part of the target of `assignment`. */ | ||
| predicate isInAssignmentContext(Expr e, AstNode assignment) { | ||
| e = assignment.(AssignExpr).getTarget() | ||
| or | ||
| e = assignment.(CompoundAssignExpr).getTarget() | ||
| or | ||
| exists(TupleExpr tuple | | ||
| isInAssignmentContext(tuple, assignment) and | ||
| e = tuple.getAnElement().getValue() | ||
| ) | ||
| } | ||
|
|
||
| /** | ||
| * Holds if `e` receives an incoming value because it is part of a binding pattern | ||
| * or assignment target. | ||
| */ | ||
| predicate hasIncomingValue(Expr e, AstNode declarationOrAssignment) { | ||
| isInBindingContext(e, declarationOrAssignment) | ||
| or | ||
| isInAssignmentContext(e, declarationOrAssignment) | ||
| } | ||
|
|
||
| /** | ||
| * Holds if `e` evaluates to a result. | ||
| */ | ||
| predicate hasResultValue(Expr e) { | ||
| not isInTypeContext(e) and | ||
| not isInBindingContext(e, _) and | ||
| not isInAssignmentContext(e, any(AssignExpr n)) and // non-compound assignment target | ||
| not e instanceof IdentifierLabel | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /** Re-exports all the files in the internal dataflow folder (except DataFlowPublic). */ | ||
|
|
||
| import Content | ||
| import DataFlowGraph | ||
| import DataFlowInstantiation | ||
| import DataFlowNode | ||
| import DataFlowPlugin | ||
| import Step | ||
| import LocalSsa | ||
| import TaintTrackingInstantiation | ||
| import VariableRefKind |
37 changes: 37 additions & 0 deletions
37
unified/ql/lib/codeql/unified/internal/dataflow/Content.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| private import unified | ||
| private import AllDataFlow | ||
|
|
||
| private newtype TContent = | ||
| TNamedMember(string name) { | ||
| name = any(Identifier id).getValue() | ||
| or | ||
| // Tuple elements can be accessed as named members, e.g. `tuple.0`, `tuple.1`, etc, | ||
| // so just model their elements as named members. | ||
| name = [0 .. 20].toString() | ||
| } | ||
|
|
||
| class Content extends TContent { | ||
| string asNamedMember() { this = TNamedMember(result) } | ||
|
|
||
| string toString() { result = this.asNamedMember() } | ||
|
|
||
| Location getLocation() { none() } | ||
| } | ||
|
|
||
| private newtype TContentSet = TSingleton(Content content) | ||
|
|
||
| class ContentSet extends TContentSet { | ||
| Content asSingleton() { this = TSingleton(result) } | ||
|
|
||
| string toString() { result = this.asSingleton().toString() } | ||
|
|
||
| Location getLocation() { result = this.asSingleton().getLocation() } | ||
|
|
||
| Content getAStoreContent() { result = this.asSingleton() } | ||
|
|
||
| Content getAReadContent() { result = this.asSingleton() } | ||
| } | ||
|
|
||
| module ContentSet { | ||
| ContentSet namedMember(string name) { result.asSingleton().asNamedMember() = name } | ||
| } |
118 changes: 118 additions & 0 deletions
118
unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| private import unified | ||
| private import AllDataFlow | ||
|
|
||
| predicate step(Node node1, Step step, Node node2) { | ||
| any(DataFlowPlugin p).step(node1, step, node2) | ||
| or | ||
| exists(VariableDeclaration decl | | ||
| node1.isResultValue(decl.getValue()) and | ||
| step.value() and | ||
| node2.isIncomingValue(decl.getPattern()) | ||
|
hvitved marked this conversation as resolved.
|
||
| ) | ||
| or | ||
| exists(AssignExpr assign | | ||
| node1.isResultValue(assign.getValue()) and | ||
| step.value() and | ||
| node2.isIncomingValue(assign.getTarget()) | ||
| ) | ||
| or | ||
| exists(LocalVariableAccess access | | ||
| node1.isLocalVariableRead(access, access.getLocalVariable()) and | ||
| step.value() and | ||
| node2.isResultValue(access) | ||
| or | ||
| node1.isIncomingValue(access) and | ||
| step.value() and | ||
| node2.isLocalVariableWrite(access, access.getLocalVariable()) | ||
| or | ||
| node1.isPostUpdate(access) and | ||
| step.value() and | ||
| node2.isLocalVariablePostUpdate(access, access.getLocalVariable()) | ||
| ) | ||
| or | ||
| exists(UnqualifiedMemberAccess access | access.isInstanceAccess() | | ||
| node1.isLocalVariableRead(access, access.getImplicitQualifierVariable()) and | ||
| step.readName(access.getName()) and | ||
| node2.isResultValue(access) | ||
| or | ||
| (node1.isIncomingValue(access) or node1.isPostUpdate(access)) and | ||
| step.storeName(access.getName()) and | ||
| node2.isLocalVariablePostUpdate(access, access.getImplicitQualifierVariable()) | ||
| ) | ||
| or | ||
| exists(StringInterpolationExpr expr | | ||
| node1.isResultValue(expr.getAnElement()) and | ||
| step.taint() and | ||
| node2.isResultValue(expr) | ||
| ) | ||
| or | ||
| exists(TupleExpr expr, int i | | ||
| node1.isResultValue(expr.getElement(i).getValue()) and | ||
| step.storeName(i.toString()) and | ||
| node2.isResultValue(expr) | ||
| or | ||
| node1.isIncomingValue(expr) and | ||
| step.readName(i.toString()) and | ||
| node2.isIncomingValue(expr.getElement(i).getValue()) | ||
| ) | ||
| or | ||
| exists(MemberAccessExpr expr | | ||
| node1.isResultValue(expr.getBase()) and | ||
| step.readName(expr.getMemberName()) and | ||
| node2.isResultValue(expr) | ||
| or | ||
| (node1.isIncomingValue(expr) or node1.isPostUpdate(expr)) and | ||
| step.storeName(expr.getMemberName()) and | ||
| node2.isPostUpdate(expr.getBase()) | ||
| ) | ||
| or | ||
| none() // Temporarily disable compilation errors from unsatisfiable types | ||
| } | ||
|
|
||
| /** Holds if `node` should be included in the debug view. */ | ||
| private signature predicate relevantNodeSig(AstNode node); | ||
|
|
||
| module DebugGraph<relevantNodeSig/1 relevantNode> { | ||
| private Node adjacent(Node n) { | ||
| step(n, _, result) | ||
| or | ||
| step(result, _, n) | ||
| or | ||
| localSsaStep(n, result, _) | ||
| or | ||
| localSsaStep(result, n, _) | ||
| } | ||
|
|
||
| private predicate relevantDataFlowNode(Node node) { | ||
| relevantNode(node.getWrappedAstNode()) | ||
| or | ||
| not exists(node.getWrappedAstNode()) and | ||
| relevantDataFlowNode(adjacent(node)) | ||
| } | ||
|
|
||
| query predicate nodes(Node node, string key, string value) { | ||
| relevantDataFlowNode(node) and | ||
| key = "semmle.label" and | ||
| value = node.toString() | ||
| } | ||
|
|
||
| query predicate edges(Node node1, Node node2, string key, string value) { | ||
| key = "semmle.label" and | ||
| relevantDataFlowNode(node1) and | ||
| relevantDataFlowNode(node2) and | ||
| ( | ||
| exists(Step step | | ||
| step(node1, step, node2) and | ||
| value = step.toString() | ||
| ) | ||
| or | ||
| exists(boolean isUseStep | | ||
| localSsaStep(node1, node2, isUseStep) and | ||
| if isUseStep = true then value = "use-use" else value = "def-use" | ||
| ) | ||
| or | ||
| node2 = getPostUpdateNode(node1) and | ||
| value = "post-update" | ||
| ) | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.