diff --git a/go/ql/lib/semmle/go/Concepts.qll b/go/ql/lib/semmle/go/Concepts.qll index ffa48ea9654d..c33fb0ae6bb0 100644 --- a/go/ql/lib/semmle/go/Concepts.qll +++ b/go/ql/lib/semmle/go/Concepts.qll @@ -574,19 +574,17 @@ module Cryptography { * is one) have been initialized separately. */ abstract class EncryptionOperation extends CryptographicOperation::Range { - DataFlow::Node encryptionFlowTarget; - DataFlow::Node inputNode; + /** Gets the target node for the encryption flow. */ + abstract DataFlow::Node getEncryptionFlowTarget(); override DataFlow::Node getInitialization() { - EncryptionFlow::flow(result, encryptionFlowTarget) + EncryptionFlow::flow(result, this.getEncryptionFlowTarget()) } override EncryptionAlgorithm getAlgorithm() { result = this.getInitialization().(EncryptionAlgorithmInit).getAlgorithm() } - override DataFlow::Node getAnInput() { result = inputNode } - override BlockMode getBlockMode() { result = this.getInitialization().(BlockModeInit).getMode() } @@ -601,8 +599,12 @@ module Cryptography { int inputArg; EncryptionMethodCall() { - encryptionFlowTarget = super.getReceiver() and - inputNode = super.getArgument(inputArg) + exists(super.getReceiver()) and + exists(super.getArgument(inputArg)) } + + override DataFlow::Node getEncryptionFlowTarget() { result = super.getReceiver() } + + override DataFlow::Node getAnInput() { result = super.getArgument(inputArg) } } } diff --git a/go/ql/lib/semmle/go/Decls.qll b/go/ql/lib/semmle/go/Decls.qll index 7588ab913bed..f42058cd3e88 100644 --- a/go/ql/lib/semmle/go/Decls.qll +++ b/go/ql/lib/semmle/go/Decls.qll @@ -1,7 +1,7 @@ /** * Provides classes for working with declarations. */ -overlay[local] +overlay[local?] module; import go @@ -137,6 +137,7 @@ class FuncDef extends @funcdef, StmtParent, ExprParent { /** * Gets a call to this function. */ + overlay[global] DataFlow::CallNode getACall() { result.getACallee() = this } /** Holds if this function is variadic. */ diff --git a/go/ql/lib/semmle/go/Scopes.qll b/go/ql/lib/semmle/go/Scopes.qll index 4e9a13c8ea1f..9f18290fb011 100644 --- a/go/ql/lib/semmle/go/Scopes.qll +++ b/go/ql/lib/semmle/go/Scopes.qll @@ -1,7 +1,7 @@ /** * Provides classes for working with scopes and declared objects. */ -overlay[local] +overlay[local?] module; import go @@ -418,6 +418,7 @@ class Function extends ValueEntity, @functionobject { * This includes calls that target this function indirectly, by calling an * interface method that this function implements. */ + overlay[global] pragma[nomagic] DataFlow::CallNode getACall() { this = result.getACalleeIncludingExternals().asFunction() } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index 8fca4bec8c63..603da6364df7 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -1,4 +1,4 @@ -overlay[local] +overlay[local?] module; private import go @@ -488,6 +488,7 @@ module Public { * For virtual calls, we look up possible targets in all types that implement the receiver * interface type. */ + overlay[global] Callable getACalleeIncludingExternals() { result = this.getACalleeWithoutVirtualDispatch() or @@ -504,6 +505,7 @@ module Public { * As `getACalleeIncludingExternals`, except excluding external functions (those for which * we lack a definition, such as standard library functions). */ + overlay[global] pragma[nomagic] FuncDef getACallee() { result = this.getACalleeIncludingExternals().getFuncDef() } diff --git a/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll b/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll index 7f0e52b449a2..f8714e8602ad 100644 --- a/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll +++ b/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll @@ -381,19 +381,26 @@ private module Crypto { } private class StreamReader extends EncryptionOperation { + DataFlow::Node encryptionFlowTarget; + DataFlow::Node inputNode; + StreamReader() { lookThroughPointerType(this.getType()).hasQualifiedName("crypto/cipher", "StreamReader") and - exists(DataFlow::Write w, DataFlow::Node base, Field f | - f.hasQualifiedName("crypto/cipher", "StreamReader", "S") and - w.writesField(base, f, encryptionFlowTarget) and - DataFlow::localFlow(base, this) + exists(DataFlow::Write wS, DataFlow::Node baseS, Field fS | + fS.hasQualifiedName("crypto/cipher", "StreamReader", "S") and + wS.writesField(baseS, fS, encryptionFlowTarget) and + DataFlow::localFlow(baseS, this) ) and - exists(DataFlow::Write w, DataFlow::Node base, Field f | - f.hasQualifiedName("crypto/cipher", "StreamReader", "R") and - w.writesField(base, f, inputNode) and - DataFlow::localFlow(base, this) + exists(DataFlow::Write wR, DataFlow::Node baseR, Field fR | + fR.hasQualifiedName("crypto/cipher", "StreamReader", "R") and + wR.writesField(baseR, fR, inputNode) and + DataFlow::localFlow(baseR, this) ) } + + override DataFlow::Node getEncryptionFlowTarget() { result = encryptionFlowTarget } + + override DataFlow::Node getAnInput() { result = inputNode } } /** @@ -402,9 +409,10 @@ private module Crypto { * so it only works within one function. */ private class StreamWriter extends EncryptionOperation { + DataFlow::Node encryptionFlowTarget; + StreamWriter() { lookThroughPointerType(this.getType()).hasQualifiedName("crypto/cipher", "StreamWriter") and - inputNode = this and exists(DataFlow::Write w, DataFlow::Node base, Field f | w.writesField(base, f, encryptionFlowTarget) and f.hasQualifiedName("crypto/cipher", "StreamWriter", "S") @@ -413,6 +421,10 @@ private module Crypto { TaintTracking::localTaint(base, this.(DataFlow::PostUpdateNode).getPreUpdateNode()) ) } + + override DataFlow::Node getEncryptionFlowTarget() { result = encryptionFlowTarget } + + override DataFlow::Node getAnInput() { result = this } } } }