mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
C#: Add VS Code model editor queries
This commit is contained in:
176
csharp/ql/src/utils/modeleditor/AutomodelVsCode.qll
Normal file
176
csharp/ql/src/utils/modeleditor/AutomodelVsCode.qll
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/** Provides classes and predicates related to handling APIs for the VS Code extension. */
|
||||||
|
|
||||||
|
private import csharp
|
||||||
|
private import dotnet
|
||||||
|
private import semmle.code.csharp.dispatch.Dispatch
|
||||||
|
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||||
|
private import semmle.code.csharp.dataflow.FlowSummary
|
||||||
|
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||||
|
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||||
|
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||||
|
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||||
|
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
|
||||||
|
private import semmle.code.csharp.frameworks.Test
|
||||||
|
private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private predicate isTestNamespace(Namespace ns) {
|
||||||
|
ns.getFullName()
|
||||||
|
.matches([
|
||||||
|
"NUnit.Framework%", "Xunit%", "Microsoft.VisualStudio.TestTools.UnitTesting%", "Moq%"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test library.
|
||||||
|
*/
|
||||||
|
class TestLibrary extends RefType {
|
||||||
|
TestLibrary() { isTestNamespace(this.getNamespace()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if the given callable is not worth supporting. */
|
||||||
|
private predicate isUninteresting(DotNet::Declaration c) {
|
||||||
|
c.getDeclaringType() instanceof TestLibrary or
|
||||||
|
c.(Constructor).isParameterless() or
|
||||||
|
c.getDeclaringType() instanceof AnonymousClass
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An callable method from either the C# Standard Library, a 3rd party library, or from the source.
|
||||||
|
*/
|
||||||
|
class CallableMethod extends DotNet::Declaration {
|
||||||
|
CallableMethod() {
|
||||||
|
this.(Modifiable).isEffectivelyPublic() and
|
||||||
|
not isUninteresting(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unbound type, name and parameter types of this API.
|
||||||
|
*/
|
||||||
|
bindingset[this]
|
||||||
|
private string getSignature() {
|
||||||
|
result =
|
||||||
|
nestedName(this.getDeclaringType().getUnboundDeclaration()) + "#" + this.getName() + "(" +
|
||||||
|
parameterQualifiedTypeNamesToString(this) + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the namespace of this API.
|
||||||
|
*/
|
||||||
|
bindingset[this]
|
||||||
|
string getNamespace() { this.getDeclaringType().hasQualifiedName(result, _) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the namespace and signature of this API.
|
||||||
|
*/
|
||||||
|
bindingset[this]
|
||||||
|
string getApiName() { result = this.getNamespace() + "." + this.getSignature() }
|
||||||
|
|
||||||
|
private string getDllName() { result = this.getLocation().(Assembly).getName() }
|
||||||
|
|
||||||
|
private string getDllVersion() { result = this.getLocation().(Assembly).getVersion().toString() }
|
||||||
|
|
||||||
|
string dllName() {
|
||||||
|
result = this.getDllName()
|
||||||
|
or
|
||||||
|
not exists(this.getDllName()) and result = this.getFile().getBaseName()
|
||||||
|
}
|
||||||
|
|
||||||
|
string dllVersion() {
|
||||||
|
result = this.getDllVersion()
|
||||||
|
or
|
||||||
|
not exists(this.getDllVersion()) and result = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets a node that is an input to a call to this API. */
|
||||||
|
private ArgumentNode getAnInput() {
|
||||||
|
result
|
||||||
|
.getCall()
|
||||||
|
.(DataFlowDispatch::NonDelegateDataFlowCall)
|
||||||
|
.getATarget(_)
|
||||||
|
.getUnboundDeclaration() = this
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets a node that is an output from a call to this API. */
|
||||||
|
private DataFlow::Node getAnOutput() {
|
||||||
|
exists(
|
||||||
|
Call c, DataFlowDispatch::NonDelegateDataFlowCall dc, DataFlowImplCommon::ReturnKindExt ret
|
||||||
|
|
|
||||||
|
dc.getDispatchCall().getCall() = c and
|
||||||
|
c.getTarget().getUnboundDeclaration() = this
|
||||||
|
|
|
||||||
|
result = ret.getAnOutNode(dc)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if this API has a supported summary. */
|
||||||
|
pragma[nomagic]
|
||||||
|
predicate hasSummary() {
|
||||||
|
this instanceof SummarizedCallable
|
||||||
|
or
|
||||||
|
defaultAdditionalTaintStep(this.getAnInput(), _)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if this API is a known source. */
|
||||||
|
pragma[nomagic]
|
||||||
|
predicate isSource() {
|
||||||
|
this.getAnOutput() instanceof RemoteFlowSource or sourceNode(this.getAnOutput(), _)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if this API is a known sink. */
|
||||||
|
pragma[nomagic]
|
||||||
|
predicate isSink() { sinkNode(this.getAnInput(), _) }
|
||||||
|
|
||||||
|
/** Holds if this API is a known neutral. */
|
||||||
|
pragma[nomagic]
|
||||||
|
predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this API is supported by existing CodeQL libraries, that is, it is either a
|
||||||
|
* recognized source, sink or neutral or it has a flow summary.
|
||||||
|
*/
|
||||||
|
predicate isSupported() {
|
||||||
|
this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isSupported(CallableMethod callableMethod) {
|
||||||
|
callableMethod.isSupported() and result = true
|
||||||
|
or
|
||||||
|
not callableMethod.isSupported() and
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
|
||||||
|
string supportedType(CallableMethod method) {
|
||||||
|
method.isSink() and result = "sink"
|
||||||
|
or
|
||||||
|
method.isSource() and result = "source"
|
||||||
|
or
|
||||||
|
method.hasSummary() and result = "summary"
|
||||||
|
or
|
||||||
|
method.isNeutral() and result = "neutral"
|
||||||
|
or
|
||||||
|
not method.isSupported() and result = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
string methodClassification(Call method) {
|
||||||
|
method.getFile() instanceof TestFile and result = "test"
|
||||||
|
or
|
||||||
|
not method.getFile() instanceof TestFile and
|
||||||
|
result = "source"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the nested name of the declaration.
|
||||||
|
*
|
||||||
|
* If the declaration is not a nested type, the result is the same as `getName()`.
|
||||||
|
* Otherwise the name of the nested type is prefixed with a `+` and appended to
|
||||||
|
* the name of the enclosing type, which might be a nested type as well.
|
||||||
|
*/
|
||||||
|
private string nestedName(Declaration declaration) {
|
||||||
|
not exists(declaration.getDeclaringType().getUnboundDeclaration()) and
|
||||||
|
result = declaration.getName()
|
||||||
|
or
|
||||||
|
nestedName(declaration.getDeclaringType().getUnboundDeclaration()) + "+" + declaration.getName() =
|
||||||
|
result
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* @name Fetch model editor methods (application mode)
|
||||||
|
* @description A list of 3rd party APIs used in the codebase. Excludes test and generated code.
|
||||||
|
* @kind problem
|
||||||
|
* @problem.severity recommendation
|
||||||
|
* @id csharp/utils/modeleditor/fetch-application-mode-methods
|
||||||
|
* @tags modeleditor fetch methods application-mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
private import csharp
|
||||||
|
private import AutomodelVsCode
|
||||||
|
|
||||||
|
class ExternalApi extends CallableMethod {
|
||||||
|
ExternalApi() {
|
||||||
|
this.isUnboundDeclaration() and
|
||||||
|
this.fromLibrary() and
|
||||||
|
this.(Modifiable).isEffectivelyPublic()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Call aUsage(ExternalApi api) { result.getTarget().getUnboundDeclaration() = api }
|
||||||
|
|
||||||
|
from
|
||||||
|
ExternalApi api, string apiName, boolean supported, Call usage, string type, string classification
|
||||||
|
where
|
||||||
|
apiName = api.getApiName() and
|
||||||
|
supported = isSupported(api) and
|
||||||
|
usage = aUsage(api) and
|
||||||
|
type = supportedType(api) and
|
||||||
|
classification = methodClassification(usage)
|
||||||
|
select usage, apiName, supported.toString(), "supported", api.dllName(), api.dllVersion(), type,
|
||||||
|
"type", classification, "classification"
|
||||||
25
csharp/ql/src/utils/modeleditor/FetchFrameworkModeMethods.ql
Normal file
25
csharp/ql/src/utils/modeleditor/FetchFrameworkModeMethods.ql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* @name Fetch model editor methods (framework mode)
|
||||||
|
* @description A list of APIs callable by consumers. Excludes test and generated code.
|
||||||
|
* @kind problem
|
||||||
|
* @problem.severity recommendation
|
||||||
|
* @id csharp/utils/modeleditor/fetch-framework-mode-methods
|
||||||
|
* @tags modeleditor fetch methods framework-mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
private import csharp
|
||||||
|
private import dotnet
|
||||||
|
private import semmle.code.csharp.frameworks.Test
|
||||||
|
private import AutomodelVsCode
|
||||||
|
|
||||||
|
class PublicMethod extends CallableMethod {
|
||||||
|
PublicMethod() { this.fromSource() and not this.getFile() instanceof TestFile }
|
||||||
|
}
|
||||||
|
|
||||||
|
from PublicMethod publicMethod, string apiName, boolean supported, string type
|
||||||
|
where
|
||||||
|
apiName = publicMethod.getApiName() and
|
||||||
|
supported = isSupported(publicMethod) and
|
||||||
|
type = supportedType(publicMethod)
|
||||||
|
select publicMethod, apiName, supported.toString(), "supported",
|
||||||
|
publicMethod.getFile().getBaseName(), "library", type, "type", "unknown", "classification"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
| NonPublicClass.cs:9:9:9:31 | call to method WriteLine | System.Console#WriteLine(System.String) | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
|
| PublicClass.cs:9:9:9:30 | call to method WriteLine | System.Console#WriteLine(System.String) | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
|
| PublicClass.cs:14:9:14:30 | call to method WriteLine | System.Console#WriteLine(System.String) | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
|
| PublicClass.cs:19:9:19:51 | call to method WriteLine | System.Console#WriteLine(System.String) | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
|
| PublicClass.cs:19:33:19:50 | call to method ReadLine | System.Console#ReadLine() | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
|
| PublicClass.cs:19:33:19:50 | call to method ReadLine | System.Console#ReadLine() | true | supported | System.Console | 7.0.0.0 | source | type | source | classification |
|
||||||
|
| PublicClass.cs:24:9:24:30 | call to method WriteLine | System.Console#WriteLine(System.String) | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
|
| PublicInterface.cs:11:9:11:30 | call to method WriteLine | System.Console#WriteLine(System.String) | true | supported | System.Console | 7.0.0.0 | neutral | type | source | classification |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
utils/modeleditor/FetchApplicationModeMethods.ql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
| PublicClass.cs:7:17:7:21 | stuff | GitHub.CodeQL.PublicClass#stuff(System.String) | false | supported | PublicClass.cs | library | | type | unknown | classification |
|
||||||
|
| PublicClass.cs:12:24:12:34 | staticStuff | GitHub.CodeQL.PublicClass#staticStuff(System.String) | false | supported | PublicClass.cs | library | | type | unknown | classification |
|
||||||
|
| PublicClass.cs:17:20:17:33 | nonPublicStuff | GitHub.CodeQL.PublicClass#nonPublicStuff(System.String) | false | supported | PublicClass.cs | library | | type | unknown | classification |
|
||||||
|
| PublicInterface.cs:7:10:7:14 | stuff | GitHub.CodeQL.PublicInterface#stuff(System.String) | false | supported | PublicInterface.cs | library | | type | unknown | classification |
|
||||||
|
| PublicInterface.cs:9:17:9:27 | staticStuff | GitHub.CodeQL.PublicInterface#staticStuff(System.String) | false | supported | PublicInterface.cs | library | | type | unknown | classification |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
utils/modeleditor/FetchFrameworkModeMethods.ql
|
||||||
11
csharp/ql/test/utils/modeleditor/NonPublicClass.cs
Normal file
11
csharp/ql/test/utils/modeleditor/NonPublicClass.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.CodeQL;
|
||||||
|
|
||||||
|
class NonPublicClass
|
||||||
|
{
|
||||||
|
public void noCandidates(String here)
|
||||||
|
{
|
||||||
|
Console.WriteLine(here);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
csharp/ql/test/utils/modeleditor/PublicClass.cs
Normal file
26
csharp/ql/test/utils/modeleditor/PublicClass.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.CodeQL;
|
||||||
|
|
||||||
|
public class PublicClass
|
||||||
|
{
|
||||||
|
public void stuff(String arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void staticStuff(String arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void nonPublicStuff(String arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg + Console.ReadLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void internalStuff(String arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
csharp/ql/test/utils/modeleditor/PublicInterface.cs
Normal file
13
csharp/ql/test/utils/modeleditor/PublicInterface.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.CodeQL;
|
||||||
|
|
||||||
|
public interface PublicInterface
|
||||||
|
{
|
||||||
|
void stuff(String arg);
|
||||||
|
|
||||||
|
static void staticStuff(String arg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,4 +30,5 @@
|
|||||||
- /Diagnostics/Internal/.*/
|
- /Diagnostics/Internal/.*/
|
||||||
- exclude:
|
- exclude:
|
||||||
tags contain:
|
tags contain:
|
||||||
|
- modeleditor
|
||||||
- modelgenerator
|
- modelgenerator
|
||||||
|
|||||||
@@ -31,4 +31,5 @@
|
|||||||
- /Diagnostics/Internal/.*/
|
- /Diagnostics/Internal/.*/
|
||||||
- exclude:
|
- exclude:
|
||||||
tags contain:
|
tags contain:
|
||||||
|
- modeleditor
|
||||||
- modelgenerator
|
- modelgenerator
|
||||||
|
|||||||
@@ -42,4 +42,5 @@
|
|||||||
- /Diagnostics/Internal/.*/
|
- /Diagnostics/Internal/.*/
|
||||||
- exclude:
|
- exclude:
|
||||||
tags contain:
|
tags contain:
|
||||||
|
- modeleditor
|
||||||
- model-generator
|
- model-generator
|
||||||
|
|||||||
@@ -36,4 +36,5 @@
|
|||||||
- /Diagnostics/Internal/.*/
|
- /Diagnostics/Internal/.*/
|
||||||
- exclude:
|
- exclude:
|
||||||
tags contain:
|
tags contain:
|
||||||
|
- modeleditor
|
||||||
- modelgenerator
|
- modelgenerator
|
||||||
|
|||||||
Reference in New Issue
Block a user