mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
Merge branch 'main' into atorralba/android-implicit-pending-intents
This commit is contained in:
@@ -27,4 +27,4 @@
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
|
||||
# QL for QL reviewers
|
||||
/ql/ @erik-krogh @tausbn
|
||||
/ql/ @github/codeql-ql-for-ql-reviewers
|
||||
@@ -4,6 +4,9 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
|
||||
|
||||
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com).
|
||||
|
||||
## Change notes
|
||||
|
||||
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
|
||||
|
||||
## Submitting a new experimental query
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
|
||||
more accurate length for integers formatted with `%x`
|
||||
1
cpp/ql/lib/change-notes/released/0.0.6.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.7-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -382,6 +382,9 @@ private int lengthInBase10(float f) {
|
||||
result = f.log10().floor() + 1
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isPointerTypeWithBase(Type base, PointerType pt) { base = pt.getBaseType() }
|
||||
|
||||
bindingset[expr]
|
||||
private BufferWriteEstimationReason getEstimationReasonForIntegralExpression(Expr expr) {
|
||||
// we consider the range analysis non trivial if it
|
||||
@@ -399,6 +402,18 @@ private BufferWriteEstimationReason getEstimationReasonForIntegralExpression(Exp
|
||||
else result = TTypeBoundsAnalysis()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of hex digits required to represent the integer represented by `f`.
|
||||
*
|
||||
* `f` is assumed to be nonnegative.
|
||||
*/
|
||||
bindingset[f]
|
||||
private int lengthInBase16(float f) {
|
||||
f = 0 and result = 1
|
||||
or
|
||||
result = (f.log2() / 4.0).floor() + 1
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent format strings that occur as arguments to invocations of formatting functions.
|
||||
*/
|
||||
@@ -950,19 +965,19 @@ class FormatLiteral extends Literal {
|
||||
(
|
||||
conv = ["s", "S"] and
|
||||
len = "h" and
|
||||
result.(PointerType).getBaseType() instanceof PlainCharType
|
||||
isPointerTypeWithBase(any(PlainCharType plainCharType), result)
|
||||
or
|
||||
conv = ["s", "S"] and
|
||||
len = ["l", "w"] and
|
||||
result.(PointerType).getBaseType() = this.getWideCharType()
|
||||
isPointerTypeWithBase(this.getWideCharType(), result)
|
||||
or
|
||||
conv = "s" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result.(PointerType).getBaseType() = this.getDefaultCharType()
|
||||
isPointerTypeWithBase(this.getDefaultCharType(), result)
|
||||
or
|
||||
conv = "S" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
|
||||
isPointerTypeWithBase(this.getNonDefaultCharType(), result)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1253,23 +1268,42 @@ class FormatLiteral extends Literal {
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "x" and
|
||||
// e.g. "12345678"
|
||||
exists(int sizeBytes, int baseLen |
|
||||
sizeBytes =
|
||||
min(int bytes |
|
||||
bytes = this.getIntegralDisplayType(n).getSize()
|
||||
exists(int baseLen, int typeBasedBound, int valueBasedBound |
|
||||
typeBasedBound =
|
||||
min(int digits |
|
||||
digits = 2 * this.getIntegralDisplayType(n).getSize()
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isUnsigned() and bytes = t.getSize()
|
||||
t.isUnsigned() and
|
||||
digits = 2 * t.getSize()
|
||||
)
|
||||
) and
|
||||
baseLen = sizeBytes * 2 and
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis()
|
||||
exists(Expr arg, float lower, float upper, float typeLower, float typeUpper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted()) and
|
||||
typeLower = exprMinVal(arg.getFullyConverted()) and
|
||||
typeUpper = exprMaxVal(arg.getFullyConverted())
|
||||
|
|
||||
valueBasedBound =
|
||||
lengthInBase16(max(float cand |
|
||||
// If lower can be negative we use `(unsigned)-1` as the candidate value.
|
||||
lower < 0 and
|
||||
cand = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
|
||||
or
|
||||
cand = upper
|
||||
)) and
|
||||
(
|
||||
if lower > typeLower or upper < typeUpper
|
||||
then reason = TValueFlowAnalysis()
|
||||
else reason = TTypeBoundsAnalysis()
|
||||
)
|
||||
) and
|
||||
baseLen = valueBasedBound.minimum(typeBasedBound) and
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "p" and
|
||||
exists(PointerType ptrType, int baseLen |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### New Queries
|
||||
|
||||
@@ -22,11 +22,13 @@ import semmle.code.cpp.dataflow.DataFlow
|
||||
* Holds if `sub` is guarded by a condition which ensures that
|
||||
* `left >= right`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
pragma[nomagic]
|
||||
predicate isGuarded(SubExpr sub, Expr left, Expr right) {
|
||||
exists(GuardCondition guard, int k |
|
||||
guard.controls(sub.getBasicBlock(), _) and
|
||||
guard.ensuresLt(left, right, k, sub.getBasicBlock(), false) and
|
||||
exprIsSubLeftOrLess(pragma[only_bind_into](sub), _) and // Manual magic
|
||||
exists(GuardCondition guard, int k, BasicBlock bb |
|
||||
pragma[only_bind_into](bb) = sub.getBasicBlock() and
|
||||
guard.controls(pragma[only_bind_into](bb), _) and
|
||||
guard.ensuresLt(left, right, k, bb, false) and
|
||||
k >= 0
|
||||
)
|
||||
}
|
||||
@@ -36,47 +38,56 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
|
||||
* `sub.getLeftOperand()`.
|
||||
*/
|
||||
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
|
||||
n.asExpr() = sub.getLeftOperand()
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// dataflow
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
(
|
||||
DataFlow::localFlowStep(n, other) or
|
||||
DataFlow::localFlowStep(other, n)
|
||||
interestingSubExpr(sub, _) and // Manual magic
|
||||
(
|
||||
n.asExpr() = sub.getLeftOperand()
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// dataflow
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
(
|
||||
DataFlow::localFlowStep(n, other) or
|
||||
DataFlow::localFlowStep(other, n)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// guard constraining `sub`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `other`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
|
||||
p <= 1 and
|
||||
q <= 0
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `n`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
|
||||
p >= 1 and
|
||||
q >= 0
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// guard constraining `sub`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `other`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
|
||||
p <= 1 and
|
||||
q <= 0
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `n`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
|
||||
p >= 1 and
|
||||
q >= 0
|
||||
)
|
||||
}
|
||||
|
||||
from RelationalOperation ro, SubExpr sub
|
||||
where
|
||||
not isFromMacroDefinition(ro) and
|
||||
predicate interestingSubExpr(SubExpr sub, RelationalOperation ro) {
|
||||
not isFromMacroDefinition(sub) and
|
||||
ro.getLesserOperand().getValue().toInt() = 0 and
|
||||
ro.getGreaterOperand() = sub and
|
||||
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
|
||||
exprMightOverflowNegatively(sub.getFullyConverted()) and // generally catches false positives involving constants
|
||||
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand())) // generally catches false positives where there's a relation between the left and right operands
|
||||
// generally catches false positives involving constants
|
||||
exprMightOverflowNegatively(sub.getFullyConverted())
|
||||
}
|
||||
|
||||
from RelationalOperation ro, SubExpr sub
|
||||
where
|
||||
interestingSubExpr(sub, ro) and
|
||||
not isFromMacroDefinition(ro) and
|
||||
// generally catches false positives where there's a relation between the left and right operands
|
||||
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand()))
|
||||
select ro, "Unsigned subtraction can never be negative."
|
||||
|
||||
1
cpp/ql/src/change-notes/released/0.0.6.md
Normal file
1
cpp/ql/src/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.7-dev
|
||||
groups: cpp
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
| tests.c:120:3:120:9 | call to sprintf | This 'call to sprintf' operation requires 17 bytes but the destination is only 1 bytes. |
|
||||
| tests.c:121:3:121:9 | call to sprintf | This 'call to sprintf' operation requires 17 bytes but the destination is only 16 bytes. |
|
||||
| tests.c:136:2:136:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:186:3:186:9 | call to sprintf | This 'call to sprintf' operation requires 9 bytes but the destination is only 2 bytes. |
|
||||
| tests.c:189:3:189:9 | call to sprintf | This 'call to sprintf' operation requires 3 bytes but the destination is only 2 bytes. |
|
||||
| unions.c:26:2:26:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. |
|
||||
| unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 15 bytes. |
|
||||
| unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. |
|
||||
|
||||
@@ -169,3 +169,27 @@ void testVarSizeStruct()
|
||||
|
||||
snprintf(s->data, 10, "abcdefghijklmnopqrstuvwxyz"); // GOOD
|
||||
}
|
||||
|
||||
void tesHexBounds(int x) {
|
||||
char buffer2[2];
|
||||
char buffer3[3];
|
||||
char buffer5[5];
|
||||
|
||||
sprintf(buffer2, "%x", 1); // GOOD
|
||||
sprintf(buffer3, "%x", 16); // GOOD
|
||||
sprintf(buffer5, "%x", (unsigned short)x); // GOOD: bounded by conversion
|
||||
if (x < 16 && x > 0) {
|
||||
sprintf(buffer2, "%x", x); // GOOD: bounded by check
|
||||
}
|
||||
|
||||
if (x < 16) {
|
||||
sprintf(buffer2, "%x", x); // BAD: negative values
|
||||
}
|
||||
if (x <= 16 && x > 0) {
|
||||
sprintf(buffer2, "%x", x); // BAD: bound too loose
|
||||
}
|
||||
|
||||
if(x < 0x10000 && x > 0) {
|
||||
sprintf(buffer5, "%x", x); // GOOD: bounded by check
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Remove 'using_global' relation.
|
||||
compatibility: backwards
|
||||
using_global.rel: delete
|
||||
5
csharp/downgrades/qlpack.yml
Normal file
5
csharp/downgrades/qlpack.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
name: codeql/csharp-downgrades
|
||||
groups: csharp
|
||||
version: 0.0.6-dev
|
||||
downgrades: .
|
||||
library: true
|
||||
@@ -47,6 +47,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.using_directive_location(this, Context.CreateLocation(ReportingLocation));
|
||||
}
|
||||
|
||||
if (node.GlobalKeyword.Kind() == SyntaxKind.GlobalKeyword)
|
||||
{
|
||||
trapFile.using_global(this);
|
||||
}
|
||||
|
||||
if (parent is not null)
|
||||
{
|
||||
trapFile.parent_namespace_declaration(this, parent);
|
||||
|
||||
@@ -68,19 +68,19 @@ namespace Semmle.Extraction.CSharp
|
||||
return symbol.CanBeReferencedByName ? name : name.Substring(symbol.Name.LastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
private static IEnumerable<SyntaxToken> GetModifiers<T>(this ISymbol symbol, Func<T, IEnumerable<SyntaxToken>> getModifierTokens) =>
|
||||
symbol.DeclaringSyntaxReferences
|
||||
.Select(r => r.GetSyntax())
|
||||
.OfType<T>()
|
||||
.SelectMany(getModifierTokens);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the source-level modifiers belonging to this symbol, if any.
|
||||
/// </summary>
|
||||
public static IEnumerable<string> GetSourceLevelModifiers(this ISymbol symbol)
|
||||
{
|
||||
var methodModifiers = symbol.DeclaringSyntaxReferences
|
||||
.Select(r => r.GetSyntax())
|
||||
.OfType<Microsoft.CodeAnalysis.CSharp.Syntax.BaseMethodDeclarationSyntax>()
|
||||
.SelectMany(md => md.Modifiers);
|
||||
var typeModifers = symbol.DeclaringSyntaxReferences
|
||||
.Select(r => r.GetSyntax())
|
||||
.OfType<Microsoft.CodeAnalysis.CSharp.Syntax.TypeDeclarationSyntax>()
|
||||
.SelectMany(cd => cd.Modifiers);
|
||||
var methodModifiers = symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.BaseMethodDeclarationSyntax>(md => md.Modifiers);
|
||||
var typeModifers = symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.TypeDeclarationSyntax>(cd => cd.Modifiers);
|
||||
return methodModifiers.Concat(typeModifers).Select(m => m.Text);
|
||||
}
|
||||
|
||||
@@ -277,10 +277,8 @@ namespace Semmle.Extraction.CSharp
|
||||
trapFile.Write("::");
|
||||
}
|
||||
|
||||
private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined)
|
||||
{
|
||||
private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
|
||||
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
|
||||
}
|
||||
|
||||
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||
{
|
||||
@@ -456,10 +454,8 @@ namespace Semmle.Extraction.CSharp
|
||||
trapFile.Write('>');
|
||||
}
|
||||
|
||||
private static void BuildFunctionPointerTypeDisplayName(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile)
|
||||
{
|
||||
private static void BuildFunctionPointerTypeDisplayName(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile) =>
|
||||
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildDisplayName(cx, trapFile));
|
||||
}
|
||||
|
||||
private static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Context cx, TextWriter trapFile, bool constructUnderlyingTupleType)
|
||||
{
|
||||
|
||||
@@ -17,723 +17,441 @@ namespace Semmle.Extraction.CSharp
|
||||
/// </remarks>
|
||||
internal static class Tuples
|
||||
{
|
||||
internal static void assemblies(this System.IO.TextWriter trapFile, Assembly assembly, Extraction.Entities.File file, string identifier, string name, string version)
|
||||
{
|
||||
internal static void assemblies(this System.IO.TextWriter trapFile, Assembly assembly, Extraction.Entities.File file, string identifier, string name, string version) =>
|
||||
trapFile.WriteTuple("assemblies", assembly, file, identifier, name, version);
|
||||
}
|
||||
|
||||
internal static void accessor_location(this TextWriter trapFile, Accessor accessorKey, Location location)
|
||||
{
|
||||
internal static void accessor_location(this TextWriter trapFile, Accessor accessorKey, Location location) =>
|
||||
trapFile.WriteTuple("accessor_location", accessorKey, location);
|
||||
}
|
||||
|
||||
internal static void accessors(this TextWriter trapFile, Accessor accessorKey, int kind, string name, Property propKey, Accessor unboundAccessor)
|
||||
{
|
||||
internal static void accessors(this TextWriter trapFile, Accessor accessorKey, int kind, string name, Property propKey, Accessor unboundAccessor) =>
|
||||
trapFile.WriteTuple("accessors", accessorKey, kind, name, propKey, unboundAccessor);
|
||||
}
|
||||
|
||||
internal static void init_only_accessors(this TextWriter trapFile, Accessor accessorKey)
|
||||
{
|
||||
internal static void init_only_accessors(this TextWriter trapFile, Accessor accessorKey) =>
|
||||
trapFile.WriteTuple("init_only_accessors", accessorKey);
|
||||
}
|
||||
|
||||
internal static void array_element_type(this TextWriter trapFile, ArrayType array, int dimension, int rank, Type elementType)
|
||||
{
|
||||
internal static void array_element_type(this TextWriter trapFile, ArrayType array, int dimension, int rank, Type elementType) =>
|
||||
trapFile.WriteTuple("array_element_type", array, dimension, rank, elementType);
|
||||
}
|
||||
|
||||
internal static void attributes(this TextWriter trapFile, Attribute attribute, Type attributeType, IEntity entity)
|
||||
{
|
||||
internal static void attributes(this TextWriter trapFile, Attribute attribute, Type attributeType, IEntity entity) =>
|
||||
trapFile.WriteTuple("attributes", attribute, attributeType, entity);
|
||||
}
|
||||
|
||||
internal static void attribute_location(this TextWriter trapFile, Attribute attribute, Location location)
|
||||
{
|
||||
internal static void attribute_location(this TextWriter trapFile, Attribute attribute, Location location) =>
|
||||
trapFile.WriteTuple("attribute_location", attribute, location);
|
||||
}
|
||||
|
||||
internal static void catch_type(this TextWriter trapFile, Entities.Statements.Catch @catch, Type type, bool explicityCaught)
|
||||
{
|
||||
internal static void catch_type(this TextWriter trapFile, Entities.Statements.Catch @catch, Type type, bool explicityCaught) =>
|
||||
trapFile.WriteTuple("catch_type", @catch, type, explicityCaught ? 1 : 2);
|
||||
}
|
||||
|
||||
internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, bool isAsync)
|
||||
{
|
||||
internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, bool isAsync) =>
|
||||
trapFile.WriteTuple("foreach_stmt_info", @foreach, isAsync ? 2 : 1);
|
||||
}
|
||||
|
||||
internal static void foreach_stmt_desugar(this TextWriter trapFile, Entities.Statements.ForEach @foreach, IEntity entity,
|
||||
Entities.Statements.ForEach.ForeachSymbolType type)
|
||||
{
|
||||
trapFile.WriteTuple("foreach_stmt_desugar", @foreach, entity, (int)type);
|
||||
}
|
||||
Entities.Statements.ForEach.ForeachSymbolType type) => trapFile.WriteTuple("foreach_stmt_desugar", @foreach, entity, (int)type);
|
||||
|
||||
internal static void commentblock(this TextWriter trapFile, CommentBlock k)
|
||||
{
|
||||
internal static void commentblock(this TextWriter trapFile, CommentBlock k) =>
|
||||
trapFile.WriteTuple("commentblock", k);
|
||||
}
|
||||
|
||||
internal static void commentblock_binding(this TextWriter trapFile, CommentBlock commentBlock, Label entity, CommentBinding binding)
|
||||
{
|
||||
internal static void commentblock_binding(this TextWriter trapFile, CommentBlock commentBlock, Label entity, CommentBinding binding) =>
|
||||
trapFile.WriteTuple("commentblock_binding", commentBlock, entity, (int)binding);
|
||||
}
|
||||
|
||||
internal static void commentblock_child(this TextWriter trapFile, CommentBlock commentBlock, CommentLine commentLine, int child)
|
||||
{
|
||||
internal static void commentblock_child(this TextWriter trapFile, CommentBlock commentBlock, CommentLine commentLine, int child) =>
|
||||
trapFile.WriteTuple("commentblock_child", commentBlock, commentLine, child);
|
||||
}
|
||||
|
||||
internal static void commentblock_location(this TextWriter trapFile, CommentBlock k, Location l)
|
||||
{
|
||||
internal static void commentblock_location(this TextWriter trapFile, CommentBlock k, Location l) =>
|
||||
trapFile.WriteTuple("commentblock_location", k, l);
|
||||
}
|
||||
|
||||
internal static void commentline(this TextWriter trapFile, CommentLine commentLine, CommentLineType type, string text, string rawtext)
|
||||
{
|
||||
internal static void commentline(this TextWriter trapFile, CommentLine commentLine, CommentLineType type, string text, string rawtext) =>
|
||||
trapFile.WriteTuple("commentline", commentLine, (int)type, text, rawtext);
|
||||
}
|
||||
|
||||
internal static void commentline_location(this TextWriter trapFile, CommentLine commentLine, Location location)
|
||||
{
|
||||
internal static void commentline_location(this TextWriter trapFile, CommentLine commentLine, Location location) =>
|
||||
trapFile.WriteTuple("commentline_location", commentLine, location);
|
||||
}
|
||||
|
||||
internal static void compilation_args(this TextWriter trapFile, Compilation compilation, int index, string arg)
|
||||
{
|
||||
internal static void compilation_args(this TextWriter trapFile, Compilation compilation, int index, string arg) =>
|
||||
trapFile.WriteTuple("compilation_args", compilation, index, arg);
|
||||
}
|
||||
|
||||
internal static void compilation_compiling_files(this TextWriter trapFile, Compilation compilation, int index, Extraction.Entities.File file)
|
||||
{
|
||||
internal static void compilation_compiling_files(this TextWriter trapFile, Compilation compilation, int index, Extraction.Entities.File file) =>
|
||||
trapFile.WriteTuple("compilation_compiling_files", compilation, index, file);
|
||||
}
|
||||
|
||||
internal static void compilation_referencing_files(this TextWriter trapFile, Compilation compilation, int index, Extraction.Entities.File file)
|
||||
{
|
||||
internal static void compilation_referencing_files(this TextWriter trapFile, Compilation compilation, int index, Extraction.Entities.File file) =>
|
||||
trapFile.WriteTuple("compilation_referencing_files", compilation, index, file);
|
||||
}
|
||||
|
||||
internal static void compilation_finished(this TextWriter trapFile, Compilation compilation, float cpuSeconds, float elapsedSeconds)
|
||||
{
|
||||
internal static void compilation_finished(this TextWriter trapFile, Compilation compilation, float cpuSeconds, float elapsedSeconds) =>
|
||||
trapFile.WriteTuple("compilation_finished", compilation, cpuSeconds, elapsedSeconds);
|
||||
}
|
||||
|
||||
internal static void compilation_time(this TextWriter trapFile, Compilation compilation, int num, int index, float metric)
|
||||
{
|
||||
internal static void compilation_time(this TextWriter trapFile, Compilation compilation, int num, int index, float metric) =>
|
||||
trapFile.WriteTuple("compilation_time", compilation, num, index, metric);
|
||||
}
|
||||
|
||||
internal static void compilations(this TextWriter trapFile, Compilation compilation, string cwd)
|
||||
{
|
||||
internal static void compilations(this TextWriter trapFile, Compilation compilation, string cwd) =>
|
||||
trapFile.WriteTuple("compilations", compilation, cwd);
|
||||
}
|
||||
|
||||
internal static void compilation_assembly(this TextWriter trapFile, Compilation compilation, Assembly assembly)
|
||||
{
|
||||
internal static void compilation_assembly(this TextWriter trapFile, Compilation compilation, Assembly assembly) =>
|
||||
trapFile.WriteTuple("compilation_assembly", compilation, assembly);
|
||||
}
|
||||
|
||||
internal static void compiler_generated(this TextWriter trapFile, IEntity entity)
|
||||
{
|
||||
internal static void compiler_generated(this TextWriter trapFile, IEntity entity) =>
|
||||
trapFile.WriteTuple("compiler_generated", entity);
|
||||
}
|
||||
|
||||
internal static void conditional_access(this TextWriter trapFile, Expression access)
|
||||
{
|
||||
internal static void conditional_access(this TextWriter trapFile, Expression access) =>
|
||||
trapFile.WriteTuple("conditional_access", access);
|
||||
}
|
||||
|
||||
internal static void constant_value(this TextWriter trapFile, IEntity field, string value)
|
||||
{
|
||||
internal static void constant_value(this TextWriter trapFile, IEntity field, string value) =>
|
||||
trapFile.WriteTuple("constant_value", field, value);
|
||||
}
|
||||
|
||||
internal static void constructed_generic(this TextWriter trapFile, IEntity constructedTypeOrMethod, IEntity unboundTypeOrMethod)
|
||||
{
|
||||
internal static void constructed_generic(this TextWriter trapFile, IEntity constructedTypeOrMethod, IEntity unboundTypeOrMethod) =>
|
||||
trapFile.WriteTuple("constructed_generic", constructedTypeOrMethod, unboundTypeOrMethod);
|
||||
}
|
||||
|
||||
internal static void constructor_location(this TextWriter trapFile, Constructor constructor, Location location)
|
||||
{
|
||||
internal static void constructor_location(this TextWriter trapFile, Constructor constructor, Location location) =>
|
||||
trapFile.WriteTuple("constructor_location", constructor, location);
|
||||
}
|
||||
|
||||
internal static void constructors(this TextWriter trapFile, Constructor key, string name, Type definingType, Constructor originalDefinition)
|
||||
{
|
||||
internal static void constructors(this TextWriter trapFile, Constructor key, string name, Type definingType, Constructor originalDefinition) =>
|
||||
trapFile.WriteTuple("constructors", key, name, definingType, originalDefinition);
|
||||
}
|
||||
|
||||
internal static void delegate_return_type(this TextWriter trapFile, Type delegateKey, Type returnType)
|
||||
{
|
||||
internal static void delegate_return_type(this TextWriter trapFile, Type delegateKey, Type returnType) =>
|
||||
trapFile.WriteTuple("delegate_return_type", delegateKey, returnType);
|
||||
}
|
||||
|
||||
internal static void function_pointer_return_type(this TextWriter trapFile, Type functionPointer, Type returnType)
|
||||
{
|
||||
internal static void function_pointer_return_type(this TextWriter trapFile, Type functionPointer, Type returnType) =>
|
||||
trapFile.WriteTuple("function_pointer_return_type", functionPointer, returnType);
|
||||
}
|
||||
|
||||
internal static void destructor_location(this TextWriter trapFile, Destructor destructor, Location location)
|
||||
{
|
||||
internal static void destructor_location(this TextWriter trapFile, Destructor destructor, Location location) =>
|
||||
trapFile.WriteTuple("destructor_location", destructor, location);
|
||||
}
|
||||
|
||||
internal static void destructors(this TextWriter trapFile, Destructor destructor, string name, Type containingType, Destructor original)
|
||||
{
|
||||
internal static void destructors(this TextWriter trapFile, Destructor destructor, string name, Type containingType, Destructor original) =>
|
||||
trapFile.WriteTuple("destructors", destructor, name, containingType, original);
|
||||
}
|
||||
|
||||
internal static void diagnostic_for(this TextWriter trapFile, Diagnostic diag, Compilation comp, int fileNo, int index)
|
||||
{
|
||||
internal static void diagnostic_for(this TextWriter trapFile, Diagnostic diag, Compilation comp, int fileNo, int index) =>
|
||||
trapFile.WriteTuple("diagnostic_for", diag, comp, fileNo, index);
|
||||
}
|
||||
|
||||
internal static void diagnostics(this TextWriter trapFile, Diagnostic diag, int severity, string errorTag, string errorMessage, string fullErrorMessage, Location location)
|
||||
{
|
||||
internal static void diagnostics(this TextWriter trapFile, Diagnostic diag, int severity, string errorTag, string errorMessage, string fullErrorMessage, Location location) =>
|
||||
trapFile.WriteTuple("diagnostics", diag, severity, errorTag, errorMessage, fullErrorMessage, location);
|
||||
}
|
||||
|
||||
internal static void dynamic_member_name(this TextWriter trapFile, Expression e, string name)
|
||||
{
|
||||
internal static void dynamic_member_name(this TextWriter trapFile, Expression e, string name) =>
|
||||
trapFile.WriteTuple("dynamic_member_name", e, name);
|
||||
}
|
||||
|
||||
internal static void enum_underlying_type(this TextWriter trapFile, Type @enum, Type type)
|
||||
{
|
||||
internal static void enum_underlying_type(this TextWriter trapFile, Type @enum, Type type) =>
|
||||
trapFile.WriteTuple("enum_underlying_type", @enum, type);
|
||||
}
|
||||
|
||||
internal static void event_accessor_location(this TextWriter trapFile, EventAccessor accessor, Location location)
|
||||
{
|
||||
internal static void event_accessor_location(this TextWriter trapFile, EventAccessor accessor, Location location) =>
|
||||
trapFile.WriteTuple("event_accessor_location", accessor, location);
|
||||
}
|
||||
|
||||
internal static void event_accessors(this TextWriter trapFile, EventAccessor accessorKey, int type, string name, Event eventKey, EventAccessor unboundAccessor)
|
||||
{
|
||||
internal static void event_accessors(this TextWriter trapFile, EventAccessor accessorKey, int type, string name, Event eventKey, EventAccessor unboundAccessor) =>
|
||||
trapFile.WriteTuple("event_accessors", accessorKey, type, name, eventKey, unboundAccessor);
|
||||
}
|
||||
|
||||
internal static void event_location(this TextWriter trapFile, Event eventKey, Location locationKey)
|
||||
{
|
||||
internal static void event_location(this TextWriter trapFile, Event eventKey, Location locationKey) =>
|
||||
trapFile.WriteTuple("event_location", eventKey, locationKey);
|
||||
}
|
||||
|
||||
internal static void events(this TextWriter trapFile, Event eventKey, string name, Type declaringType, Type memberType, Event originalDefinition)
|
||||
{
|
||||
internal static void events(this TextWriter trapFile, Event eventKey, string name, Type declaringType, Type memberType, Event originalDefinition) =>
|
||||
trapFile.WriteTuple("events", eventKey, name, declaringType, memberType, originalDefinition);
|
||||
}
|
||||
|
||||
internal static void explicitly_implements(this TextWriter trapFile, IEntity member, Type @interface)
|
||||
{
|
||||
internal static void explicitly_implements(this TextWriter trapFile, IEntity member, Type @interface) =>
|
||||
trapFile.WriteTuple("explicitly_implements", member, @interface);
|
||||
}
|
||||
|
||||
internal static void explicitly_sized_array_creation(this TextWriter trapFile, Expression array)
|
||||
{
|
||||
internal static void explicitly_sized_array_creation(this TextWriter trapFile, Expression array) =>
|
||||
trapFile.WriteTuple("explicitly_sized_array_creation", array);
|
||||
}
|
||||
|
||||
internal static void expr_access(this TextWriter trapFile, Expression expr, IEntity access)
|
||||
{
|
||||
internal static void expr_access(this TextWriter trapFile, Expression expr, IEntity access) =>
|
||||
trapFile.WriteTuple("expr_access", expr, access);
|
||||
}
|
||||
|
||||
internal static void expr_argument(this TextWriter trapFile, Expression expr, int mode)
|
||||
{
|
||||
internal static void expr_argument(this TextWriter trapFile, Expression expr, int mode) =>
|
||||
trapFile.WriteTuple("expr_argument", expr, mode);
|
||||
}
|
||||
|
||||
internal static void expr_argument_name(this TextWriter trapFile, Expression expr, string name)
|
||||
{
|
||||
internal static void expr_argument_name(this TextWriter trapFile, Expression expr, string name) =>
|
||||
trapFile.WriteTuple("expr_argument_name", expr, name);
|
||||
}
|
||||
|
||||
internal static void expr_call(this TextWriter trapFile, Expression expr, Method target)
|
||||
{
|
||||
internal static void expr_call(this TextWriter trapFile, Expression expr, Method target) =>
|
||||
trapFile.WriteTuple("expr_call", expr, target);
|
||||
}
|
||||
|
||||
internal static void expr_compiler_generated(this TextWriter trapFile, Expression expr)
|
||||
{
|
||||
internal static void expr_compiler_generated(this TextWriter trapFile, Expression expr) =>
|
||||
trapFile.WriteTuple("expr_compiler_generated", expr);
|
||||
}
|
||||
|
||||
internal static void expr_flowstate(this TextWriter trapFile, Expression expr, int flowState)
|
||||
{
|
||||
internal static void expr_flowstate(this TextWriter trapFile, Expression expr, int flowState) =>
|
||||
trapFile.WriteTuple("expr_flowstate", expr, flowState);
|
||||
}
|
||||
|
||||
internal static void expr_location(this TextWriter trapFile, Expression expr, Location location)
|
||||
{
|
||||
internal static void expr_location(this TextWriter trapFile, Expression expr, Location location) =>
|
||||
trapFile.WriteTuple("expr_location", expr, location);
|
||||
}
|
||||
|
||||
internal static void expr_parent(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent)
|
||||
{
|
||||
internal static void expr_parent(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent) =>
|
||||
trapFile.WriteTuple("expr_parent", expr, child, parent);
|
||||
}
|
||||
|
||||
internal static void expr_parent_top_level(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent)
|
||||
{
|
||||
internal static void expr_parent_top_level(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent) =>
|
||||
trapFile.WriteTuple("expr_parent_top_level", expr, child, parent);
|
||||
}
|
||||
|
||||
internal static void expr_value(this TextWriter trapFile, Expression expr, string value)
|
||||
{
|
||||
internal static void expr_value(this TextWriter trapFile, Expression expr, string value) =>
|
||||
trapFile.WriteTuple("expr_value", expr, value);
|
||||
}
|
||||
|
||||
internal static void expressions(this TextWriter trapFile, Expression expr, ExprKind kind, Type exprType)
|
||||
{
|
||||
internal static void expressions(this TextWriter trapFile, Expression expr, ExprKind kind, Type exprType) =>
|
||||
trapFile.WriteTuple("expressions", expr, (int)kind, exprType);
|
||||
}
|
||||
|
||||
internal static void exprorstmt_name(this TextWriter trapFile, IEntity expr, string name)
|
||||
{
|
||||
internal static void exprorstmt_name(this TextWriter trapFile, IEntity expr, string name) =>
|
||||
trapFile.WriteTuple("exprorstmt_name", expr, name);
|
||||
}
|
||||
|
||||
internal static void extend(this TextWriter trapFile, Type type, Type super)
|
||||
{
|
||||
internal static void extend(this TextWriter trapFile, Type type, Type super) =>
|
||||
trapFile.WriteTuple("extend", type, super);
|
||||
}
|
||||
|
||||
internal static void anonymous_types(this TextWriter trapFile, Type type)
|
||||
{
|
||||
internal static void anonymous_types(this TextWriter trapFile, Type type) =>
|
||||
trapFile.WriteTuple("anonymous_types", type);
|
||||
}
|
||||
|
||||
internal static void field_location(this TextWriter trapFile, Field field, Location location)
|
||||
{
|
||||
internal static void field_location(this TextWriter trapFile, Field field, Location location) =>
|
||||
trapFile.WriteTuple("field_location", field, location);
|
||||
}
|
||||
|
||||
internal static void fields(this TextWriter trapFile, Field field, int @const, string name, Type declaringType, Type fieldType, Field unboundKey)
|
||||
{
|
||||
internal static void fields(this TextWriter trapFile, Field field, int @const, string name, Type declaringType, Type fieldType, Field unboundKey) =>
|
||||
trapFile.WriteTuple("fields", field, @const, name, declaringType, fieldType, unboundKey);
|
||||
}
|
||||
|
||||
internal static void general_type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, int hasKind)
|
||||
{
|
||||
internal static void general_type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, int hasKind) =>
|
||||
trapFile.WriteTuple("general_type_parameter_constraints", constraints, hasKind);
|
||||
}
|
||||
|
||||
internal static void has_modifiers(this TextWriter trapFile, IEntity entity, Modifier modifier)
|
||||
{
|
||||
internal static void has_modifiers(this TextWriter trapFile, IEntity entity, Modifier modifier) =>
|
||||
trapFile.WriteTuple("has_modifiers", entity, modifier);
|
||||
}
|
||||
|
||||
internal static void implement(this TextWriter trapFile, Type type, Type @interface)
|
||||
{
|
||||
internal static void implement(this TextWriter trapFile, Type type, Type @interface) =>
|
||||
trapFile.WriteTuple("implement", type, @interface);
|
||||
}
|
||||
|
||||
internal static void implicitly_typed_array_creation(this TextWriter trapFile, Expression array)
|
||||
{
|
||||
internal static void implicitly_typed_array_creation(this TextWriter trapFile, Expression array) =>
|
||||
trapFile.WriteTuple("implicitly_typed_array_creation", array);
|
||||
}
|
||||
|
||||
internal static void implicitly_typed_object_creation(this TextWriter trapFile, Expression expression)
|
||||
{
|
||||
internal static void implicitly_typed_object_creation(this TextWriter trapFile, Expression expression) =>
|
||||
trapFile.WriteTuple("implicitly_typed_object_creation", expression);
|
||||
}
|
||||
|
||||
internal static void indexer_location(this TextWriter trapFile, Indexer indexer, Location location)
|
||||
{
|
||||
internal static void indexer_location(this TextWriter trapFile, Indexer indexer, Location location) =>
|
||||
trapFile.WriteTuple("indexer_location", indexer, location);
|
||||
}
|
||||
|
||||
internal static void indexers(this TextWriter trapFile, Indexer propKey, string name, Type declaringType, Type memberType, Indexer unboundProperty)
|
||||
{
|
||||
internal static void indexers(this TextWriter trapFile, Indexer propKey, string name, Type declaringType, Type memberType, Indexer unboundProperty) =>
|
||||
trapFile.WriteTuple("indexers", propKey, name, declaringType, memberType, unboundProperty);
|
||||
}
|
||||
|
||||
internal static void local_function_stmts(this TextWriter trapFile, Entities.Statements.LocalFunction fnStmt, LocalFunction fn)
|
||||
{
|
||||
internal static void local_function_stmts(this TextWriter trapFile, Entities.Statements.LocalFunction fnStmt, LocalFunction fn) =>
|
||||
trapFile.WriteTuple("local_function_stmts", fnStmt, fn);
|
||||
}
|
||||
|
||||
internal static void local_functions(this TextWriter trapFile, LocalFunction fn, string name, Type returnType, LocalFunction unboundFn)
|
||||
{
|
||||
internal static void local_functions(this TextWriter trapFile, LocalFunction fn, string name, Type returnType, LocalFunction unboundFn) =>
|
||||
trapFile.WriteTuple("local_functions", fn, name, returnType, unboundFn);
|
||||
}
|
||||
|
||||
internal static void localvar_location(this TextWriter trapFile, LocalVariable var, Location location)
|
||||
{
|
||||
internal static void localvar_location(this TextWriter trapFile, LocalVariable var, Location location) =>
|
||||
trapFile.WriteTuple("localvar_location", var, location);
|
||||
}
|
||||
|
||||
internal static void localvars(this TextWriter trapFile, LocalVariable key, int @const, string name, int @var, Type type, Expression expr)
|
||||
{
|
||||
internal static void localvars(this TextWriter trapFile, LocalVariable key, int @const, string name, int @var, Type type, Expression expr) =>
|
||||
trapFile.WriteTuple("localvars", key, @const, name, @var, type, expr);
|
||||
}
|
||||
|
||||
public static void metadata_handle(this TextWriter trapFile, IEntity entity, Location assembly, int handleValue)
|
||||
{
|
||||
public static void metadata_handle(this TextWriter trapFile, IEntity entity, Location assembly, int handleValue) =>
|
||||
trapFile.WriteTuple("metadata_handle", entity, assembly, handleValue);
|
||||
}
|
||||
|
||||
internal static void method_location(this TextWriter trapFile, Method method, Location location)
|
||||
{
|
||||
internal static void method_location(this TextWriter trapFile, Method method, Location location) =>
|
||||
trapFile.WriteTuple("method_location", method, location);
|
||||
}
|
||||
|
||||
internal static void methods(this TextWriter trapFile, Method method, string name, Type declType, Type retType, Method originalDefinition)
|
||||
{
|
||||
internal static void methods(this TextWriter trapFile, Method method, string name, Type declType, Type retType, Method originalDefinition) =>
|
||||
trapFile.WriteTuple("methods", method, name, declType, retType, originalDefinition);
|
||||
}
|
||||
|
||||
internal static void modifiers(this TextWriter trapFile, Label entity, string modifier)
|
||||
{
|
||||
internal static void modifiers(this TextWriter trapFile, Label entity, string modifier) =>
|
||||
trapFile.WriteTuple("modifiers", entity, modifier);
|
||||
}
|
||||
|
||||
internal static void mutator_invocation_mode(this TextWriter trapFile, Expression expr, int mode)
|
||||
{
|
||||
internal static void mutator_invocation_mode(this TextWriter trapFile, Expression expr, int mode) =>
|
||||
trapFile.WriteTuple("mutator_invocation_mode", expr, mode);
|
||||
}
|
||||
|
||||
internal static void namespace_declaration_location(this TextWriter trapFile, NamespaceDeclaration decl, Location location)
|
||||
{
|
||||
internal static void namespace_declaration_location(this TextWriter trapFile, NamespaceDeclaration decl, Location location) =>
|
||||
trapFile.WriteTuple("namespace_declaration_location", decl, location);
|
||||
}
|
||||
|
||||
internal static void namespace_declarations(this TextWriter trapFile, NamespaceDeclaration decl, Namespace ns)
|
||||
{
|
||||
internal static void namespace_declarations(this TextWriter trapFile, NamespaceDeclaration decl, Namespace ns) =>
|
||||
trapFile.WriteTuple("namespace_declarations", decl, ns);
|
||||
}
|
||||
|
||||
internal static void namespaces(this TextWriter trapFile, Namespace ns, string name)
|
||||
{
|
||||
internal static void namespaces(this TextWriter trapFile, Namespace ns, string name) =>
|
||||
trapFile.WriteTuple("namespaces", ns, name);
|
||||
}
|
||||
|
||||
internal static void nested_types(this TextWriter trapFile, Type typeKey, Type declaringTypeKey, Type unboundTypeKey)
|
||||
{
|
||||
internal static void nested_types(this TextWriter trapFile, Type typeKey, Type declaringTypeKey, Type unboundTypeKey) =>
|
||||
trapFile.WriteTuple("nested_types", typeKey, declaringTypeKey, unboundTypeKey);
|
||||
}
|
||||
|
||||
internal static void nullable_underlying_type(this TextWriter trapFile, Type nullableType, Type underlyingType)
|
||||
{
|
||||
internal static void nullable_underlying_type(this TextWriter trapFile, Type nullableType, Type underlyingType) =>
|
||||
trapFile.WriteTuple("nullable_underlying_type", nullableType, underlyingType);
|
||||
}
|
||||
|
||||
internal static void nullability(this TextWriter trapFile, NullabilityEntity nullability, int annotation)
|
||||
{
|
||||
internal static void nullability(this TextWriter trapFile, NullabilityEntity nullability, int annotation) =>
|
||||
trapFile.WriteTuple("nullability", nullability, annotation);
|
||||
}
|
||||
|
||||
internal static void nullability_parent(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity parent)
|
||||
{
|
||||
internal static void nullability_parent(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity parent) =>
|
||||
trapFile.WriteTuple("nullability_parent", nullability, index, parent);
|
||||
}
|
||||
|
||||
internal static void numlines(this TextWriter trapFile, IEntity label, LineCounts lineCounts)
|
||||
{
|
||||
internal static void numlines(this TextWriter trapFile, IEntity label, LineCounts lineCounts) =>
|
||||
trapFile.WriteTuple("numlines", label, lineCounts.Total, lineCounts.Code, lineCounts.Comment);
|
||||
}
|
||||
|
||||
internal static void operator_location(this TextWriter trapFile, UserOperator @operator, Location location)
|
||||
{
|
||||
internal static void operator_location(this TextWriter trapFile, UserOperator @operator, Location location) =>
|
||||
trapFile.WriteTuple("operator_location", @operator, location);
|
||||
}
|
||||
|
||||
internal static void operators(this TextWriter trapFile, UserOperator method, string methodName, string symbol, Type classKey, Type returnType, UserOperator originalDefinition)
|
||||
{
|
||||
internal static void operators(this TextWriter trapFile, UserOperator method, string methodName, string symbol, Type classKey, Type returnType, UserOperator originalDefinition) =>
|
||||
trapFile.WriteTuple("operators", method, methodName, symbol, classKey, returnType, originalDefinition);
|
||||
}
|
||||
|
||||
internal static void overrides(this TextWriter trapFile, Method overriding, Method overridden)
|
||||
{
|
||||
internal static void overrides(this TextWriter trapFile, Method overriding, Method overridden) =>
|
||||
trapFile.WriteTuple("overrides", overriding, overridden);
|
||||
}
|
||||
|
||||
internal static void param_location(this TextWriter trapFile, Parameter param, Location location)
|
||||
{
|
||||
internal static void param_location(this TextWriter trapFile, Parameter param, Location location) =>
|
||||
trapFile.WriteTuple("param_location", param, location);
|
||||
}
|
||||
|
||||
internal static void @params(this TextWriter trapFile, Parameter param, string name, Type type, int child, Parameter.Kind mode, IEntity method, Parameter originalDefinition)
|
||||
{
|
||||
internal static void @params(this TextWriter trapFile, Parameter param, string name, Type type, int child, Parameter.Kind mode, IEntity method, Parameter originalDefinition) =>
|
||||
trapFile.WriteTuple("params", param, name, type, child, (int)mode, method, originalDefinition);
|
||||
}
|
||||
|
||||
internal static void parent_namespace(this TextWriter trapFile, IEntity type, Namespace parent)
|
||||
{
|
||||
internal static void parent_namespace(this TextWriter trapFile, IEntity type, Namespace parent) =>
|
||||
trapFile.WriteTuple("parent_namespace", type, parent);
|
||||
}
|
||||
|
||||
internal static void parent_namespace_declaration(this TextWriter trapFile, IEntity item, NamespaceDeclaration parent)
|
||||
{
|
||||
internal static void parent_namespace_declaration(this TextWriter trapFile, IEntity item, NamespaceDeclaration parent) =>
|
||||
trapFile.WriteTuple("parent_namespace_declaration", item, parent);
|
||||
}
|
||||
|
||||
internal static void pointer_referent_type(this TextWriter trapFile, PointerType pointerType, Type referentType)
|
||||
{
|
||||
internal static void pointer_referent_type(this TextWriter trapFile, PointerType pointerType, Type referentType) =>
|
||||
trapFile.WriteTuple("pointer_referent_type", pointerType, referentType);
|
||||
}
|
||||
|
||||
internal static void property_location(this TextWriter trapFile, Property property, Location location)
|
||||
{
|
||||
internal static void property_location(this TextWriter trapFile, Property property, Location location) =>
|
||||
trapFile.WriteTuple("property_location", property, location);
|
||||
}
|
||||
|
||||
internal static void properties(this TextWriter trapFile, Property propKey, string name, Type declaringType, Type memberType, Property unboundProperty)
|
||||
{
|
||||
internal static void properties(this TextWriter trapFile, Property propKey, string name, Type declaringType, Type memberType, Property unboundProperty) =>
|
||||
trapFile.WriteTuple("properties", propKey, name, declaringType, memberType, unboundProperty);
|
||||
}
|
||||
|
||||
internal static void statements(this TextWriter trapFile, Statement stmt, StmtKind kind)
|
||||
{
|
||||
internal static void statements(this TextWriter trapFile, Statement stmt, StmtKind kind) =>
|
||||
trapFile.WriteTuple("statements", stmt, (int)kind);
|
||||
}
|
||||
|
||||
internal static void specific_type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, Type baseType)
|
||||
{
|
||||
internal static void specific_type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, Type baseType) =>
|
||||
trapFile.WriteTuple("specific_type_parameter_constraints", constraints, baseType);
|
||||
}
|
||||
|
||||
internal static void specific_type_parameter_nullability(this TextWriter trapFile, TypeParameterConstraints constraints, Type baseType, NullabilityEntity nullability)
|
||||
{
|
||||
internal static void specific_type_parameter_nullability(this TextWriter trapFile, TypeParameterConstraints constraints, Type baseType, NullabilityEntity nullability) =>
|
||||
trapFile.WriteTuple("specific_type_parameter_nullability", constraints, baseType, nullability);
|
||||
}
|
||||
|
||||
internal static void function_pointer_calling_conventions(this TextWriter trapFile, FunctionPointerType type, int kind)
|
||||
{
|
||||
internal static void function_pointer_calling_conventions(this TextWriter trapFile, FunctionPointerType type, int kind) =>
|
||||
trapFile.WriteTuple("function_pointer_calling_conventions", type, kind);
|
||||
}
|
||||
|
||||
internal static void has_unmanaged_calling_conventions(this TextWriter trapFile, FunctionPointerType type, int index, Type convention)
|
||||
{
|
||||
internal static void has_unmanaged_calling_conventions(this TextWriter trapFile, FunctionPointerType type, int index, Type convention) =>
|
||||
trapFile.WriteTuple("has_unmanaged_calling_conventions", type, index, convention);
|
||||
}
|
||||
|
||||
internal static void stackalloc_array_creation(this TextWriter trapFile, Expression array)
|
||||
{
|
||||
internal static void stackalloc_array_creation(this TextWriter trapFile, Expression array) =>
|
||||
trapFile.WriteTuple("stackalloc_array_creation", array);
|
||||
}
|
||||
|
||||
internal static void stmt_location(this TextWriter trapFile, Statement stmt, Location location)
|
||||
{
|
||||
internal static void stmt_location(this TextWriter trapFile, Statement stmt, Location location) =>
|
||||
trapFile.WriteTuple("stmt_location", stmt, location);
|
||||
}
|
||||
|
||||
internal static void stmt_parent(this TextWriter trapFile, Statement stmt, int child, IStatementParentEntity parent)
|
||||
{
|
||||
internal static void stmt_parent(this TextWriter trapFile, Statement stmt, int child, IStatementParentEntity parent) =>
|
||||
trapFile.WriteTuple("stmt_parent", stmt, child, parent);
|
||||
}
|
||||
|
||||
internal static void stmt_parent_top_level(this TextWriter trapFile, Statement stmt, int child, IStatementParentEntity parent)
|
||||
{
|
||||
internal static void stmt_parent_top_level(this TextWriter trapFile, Statement stmt, int child, IStatementParentEntity parent) =>
|
||||
trapFile.WriteTuple("stmt_parent_top_level", stmt, child, parent);
|
||||
}
|
||||
|
||||
internal static void tuple_element(this TextWriter trapFile, TupleType type, int index, Field field)
|
||||
{
|
||||
internal static void tuple_element(this TextWriter trapFile, TupleType type, int index, Field field) =>
|
||||
trapFile.WriteTuple("tuple_element", type, index, field);
|
||||
}
|
||||
|
||||
internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, NamedType underlying)
|
||||
{
|
||||
internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, NamedType underlying) =>
|
||||
trapFile.WriteTuple("tuple_underlying_type", type, underlying);
|
||||
}
|
||||
|
||||
internal static void type_annotation(this TextWriter trapFile, IEntity element, Kinds.TypeAnnotation annotation)
|
||||
{
|
||||
internal static void type_annotation(this TextWriter trapFile, IEntity element, Kinds.TypeAnnotation annotation) =>
|
||||
trapFile.WriteTuple("type_annotation", element, (int)annotation);
|
||||
}
|
||||
|
||||
internal static void type_arguments(this TextWriter trapFile, Type arg, int n, IEntity typeOrMethod)
|
||||
{
|
||||
internal static void type_arguments(this TextWriter trapFile, Type arg, int n, IEntity typeOrMethod) =>
|
||||
trapFile.WriteTuple("type_arguments", arg, n, typeOrMethod);
|
||||
}
|
||||
|
||||
internal static void type_location(this TextWriter trapFile, Type type, Location location)
|
||||
{
|
||||
internal static void type_location(this TextWriter trapFile, Type type, Location location) =>
|
||||
trapFile.WriteTuple("type_location", type, location);
|
||||
}
|
||||
|
||||
internal static void type_mention(this TextWriter trapFile, TypeMention ta, Type type, IEntity parent)
|
||||
{
|
||||
internal static void type_mention(this TextWriter trapFile, TypeMention ta, Type type, IEntity parent) =>
|
||||
trapFile.WriteTuple("type_mention", ta, type, parent);
|
||||
}
|
||||
|
||||
internal static void type_mention_location(this TextWriter trapFile, TypeMention ta, Location loc)
|
||||
{
|
||||
internal static void type_mention_location(this TextWriter trapFile, TypeMention ta, Location loc) =>
|
||||
trapFile.WriteTuple("type_mention_location", ta, loc);
|
||||
}
|
||||
|
||||
internal static void type_nullability(this TextWriter trapFile, IEntity element, NullabilityEntity nullability)
|
||||
{
|
||||
internal static void type_nullability(this TextWriter trapFile, IEntity element, NullabilityEntity nullability) =>
|
||||
trapFile.WriteTuple("type_nullability", element, nullability);
|
||||
}
|
||||
|
||||
internal static void type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, TypeParameter typeParam)
|
||||
{
|
||||
internal static void type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, TypeParameter typeParam) =>
|
||||
trapFile.WriteTuple("type_parameter_constraints", constraints, typeParam);
|
||||
}
|
||||
|
||||
internal static void type_parameters(this TextWriter trapFile, TypeParameter param, int child, IEntity typeOrMethod)
|
||||
{
|
||||
internal static void type_parameters(this TextWriter trapFile, TypeParameter param, int child, IEntity typeOrMethod) =>
|
||||
trapFile.WriteTuple("type_parameters", param, child, typeOrMethod, (int)param.Variance);
|
||||
}
|
||||
|
||||
internal static void typeref_type(this TextWriter trapFile, NamedTypeRef typeref, Type type)
|
||||
{
|
||||
internal static void typeref_type(this TextWriter trapFile, NamedTypeRef typeref, Type type) =>
|
||||
trapFile.WriteTuple("typeref_type", typeref, type);
|
||||
}
|
||||
|
||||
internal static void typerefs(this TextWriter trapFile, NamedTypeRef type, string name)
|
||||
{
|
||||
internal static void typerefs(this TextWriter trapFile, NamedTypeRef type, string name) =>
|
||||
trapFile.WriteTuple("typerefs", type, name);
|
||||
}
|
||||
|
||||
internal static void types(this TextWriter trapFile, Type type, TypeKind kind, string name)
|
||||
{
|
||||
internal static void types(this TextWriter trapFile, Type type, TypeKind kind, string name) =>
|
||||
trapFile.WriteTuple("types", type, (int)kind, name);
|
||||
}
|
||||
|
||||
internal static void using_namespace_directives(this TextWriter trapFile, UsingDirective @using, Namespace ns)
|
||||
{
|
||||
internal static void using_namespace_directives(this TextWriter trapFile, UsingDirective @using, Namespace ns) =>
|
||||
trapFile.WriteTuple("using_namespace_directives", @using, ns);
|
||||
}
|
||||
|
||||
internal static void using_directive_location(this TextWriter trapFile, UsingDirective @using, Location location)
|
||||
{
|
||||
internal static void using_directive_location(this TextWriter trapFile, UsingDirective @using, Location location) =>
|
||||
trapFile.WriteTuple("using_directive_location", @using, location);
|
||||
}
|
||||
|
||||
internal static void using_static_directives(this TextWriter trapFile, UsingDirective @using, Type type)
|
||||
{
|
||||
internal static void using_static_directives(this TextWriter trapFile, UsingDirective @using, Type type) =>
|
||||
trapFile.WriteTuple("using_static_directives", @using, type);
|
||||
}
|
||||
|
||||
internal static void using_global(this TextWriter trapFile, UsingDirective @using) =>
|
||||
trapFile.WriteTuple("using_global", @using);
|
||||
|
||||
internal static void preprocessor_directive_location<TDirective>(this TextWriter trapFile,
|
||||
PreprocessorDirective<TDirective> directive, Location location)
|
||||
where TDirective : DirectiveTriviaSyntax
|
||||
{
|
||||
where TDirective : DirectiveTriviaSyntax =>
|
||||
trapFile.WriteTuple("preprocessor_directive_location", directive, location);
|
||||
}
|
||||
|
||||
internal static void preprocessor_directive_compilation<TDirective>(this TextWriter trapFile,
|
||||
PreprocessorDirective<TDirective> directive, Compilation compilation)
|
||||
where TDirective : DirectiveTriviaSyntax
|
||||
{
|
||||
where TDirective : DirectiveTriviaSyntax =>
|
||||
trapFile.WriteTuple("preprocessor_directive_compilation", directive, compilation);
|
||||
}
|
||||
|
||||
internal static void preprocessor_directive_active<TDirective>(this TextWriter trapFile,
|
||||
PreprocessorDirective<TDirective> directive, bool isActive)
|
||||
where TDirective : DirectiveTriviaSyntax
|
||||
{
|
||||
where TDirective : DirectiveTriviaSyntax =>
|
||||
trapFile.WriteTuple("preprocessor_directive_active", directive, isActive ? 1 : 0);
|
||||
}
|
||||
|
||||
internal static void pragma_warnings(this TextWriter trapFile, PragmaWarningDirective pragma, int kind)
|
||||
{
|
||||
internal static void pragma_warnings(this TextWriter trapFile, PragmaWarningDirective pragma, int kind) =>
|
||||
trapFile.WriteTuple("pragma_warnings", pragma, kind);
|
||||
}
|
||||
|
||||
internal static void pragma_warning_error_codes(this TextWriter trapFile, PragmaWarningDirective pragma, string errorCode, int child)
|
||||
{
|
||||
internal static void pragma_warning_error_codes(this TextWriter trapFile, PragmaWarningDirective pragma, string errorCode, int child) =>
|
||||
trapFile.WriteTuple("pragma_warning_error_codes", pragma, errorCode, child);
|
||||
}
|
||||
|
||||
internal static void pragma_checksums(this TextWriter trapFile, PragmaChecksumDirective pragma, Extraction.Entities.File file, string guid, string bytes)
|
||||
{
|
||||
internal static void pragma_checksums(this TextWriter trapFile, PragmaChecksumDirective pragma, Extraction.Entities.File file, string guid, string bytes) =>
|
||||
trapFile.WriteTuple("pragma_checksums", pragma, file, guid, bytes);
|
||||
}
|
||||
|
||||
internal static void directive_defines(this TextWriter trapFile, DefineDirective directive, string name)
|
||||
{
|
||||
internal static void directive_defines(this TextWriter trapFile, DefineDirective directive, string name) =>
|
||||
trapFile.WriteTuple("directive_defines", directive, name);
|
||||
}
|
||||
|
||||
internal static void directive_undefines(this TextWriter trapFile, UndefineDirective directive, string name)
|
||||
{
|
||||
internal static void directive_undefines(this TextWriter trapFile, UndefineDirective directive, string name) =>
|
||||
trapFile.WriteTuple("directive_undefines", directive, name);
|
||||
}
|
||||
|
||||
internal static void directive_warnings(this TextWriter trapFile, WarningDirective directive, string message)
|
||||
{
|
||||
internal static void directive_warnings(this TextWriter trapFile, WarningDirective directive, string message) =>
|
||||
trapFile.WriteTuple("directive_warnings", directive, message);
|
||||
}
|
||||
|
||||
internal static void directive_errors(this TextWriter trapFile, ErrorDirective directive, string message)
|
||||
{
|
||||
internal static void directive_errors(this TextWriter trapFile, ErrorDirective directive, string message) =>
|
||||
trapFile.WriteTuple("directive_errors", directive, message);
|
||||
}
|
||||
|
||||
internal static void directive_nullables(this TextWriter trapFile, NullableDirective directive, int setting, int target)
|
||||
{
|
||||
internal static void directive_nullables(this TextWriter trapFile, NullableDirective directive, int setting, int target) =>
|
||||
trapFile.WriteTuple("directive_nullables", directive, setting, target);
|
||||
}
|
||||
|
||||
internal static void directive_lines(this TextWriter trapFile, LineDirective directive, int kind)
|
||||
{
|
||||
internal static void directive_lines(this TextWriter trapFile, LineDirective directive, int kind) =>
|
||||
trapFile.WriteTuple("directive_lines", directive, kind);
|
||||
}
|
||||
|
||||
internal static void directive_line_value(this TextWriter trapFile, LineDirective directive, int line)
|
||||
{
|
||||
internal static void directive_line_value(this TextWriter trapFile, LineDirective directive, int line) =>
|
||||
trapFile.WriteTuple("directive_line_value", directive, line);
|
||||
}
|
||||
|
||||
internal static void directive_line_file(this TextWriter trapFile, LineDirective directive, Extraction.Entities.File file)
|
||||
{
|
||||
internal static void directive_line_file(this TextWriter trapFile, LineDirective directive, Extraction.Entities.File file) =>
|
||||
trapFile.WriteTuple("directive_line_file", directive, file);
|
||||
}
|
||||
|
||||
internal static void directive_regions(this TextWriter trapFile, RegionDirective directive, string name)
|
||||
{
|
||||
internal static void directive_regions(this TextWriter trapFile, RegionDirective directive, string name) =>
|
||||
trapFile.WriteTuple("directive_regions", directive, name);
|
||||
}
|
||||
|
||||
internal static void directive_endregions(this TextWriter trapFile, EndRegionDirective directive, RegionDirective start)
|
||||
{
|
||||
internal static void directive_endregions(this TextWriter trapFile, EndRegionDirective directive, RegionDirective start) =>
|
||||
trapFile.WriteTuple("directive_endregions", directive, start);
|
||||
}
|
||||
|
||||
internal static void regions(this TextWriter trapFile, RegionDirective start, EndRegionDirective end)
|
||||
{
|
||||
internal static void regions(this TextWriter trapFile, RegionDirective start, EndRegionDirective end) =>
|
||||
trapFile.WriteTuple("regions", start, end);
|
||||
}
|
||||
|
||||
internal static void directive_ifs(this TextWriter trapFile, IfDirective directive, bool branchTaken, bool conditionValue)
|
||||
{
|
||||
internal static void directive_ifs(this TextWriter trapFile, IfDirective directive, bool branchTaken, bool conditionValue) =>
|
||||
trapFile.WriteTuple("directive_ifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
|
||||
}
|
||||
|
||||
internal static void directive_elifs(this TextWriter trapFile, ElifDirective directive, bool branchTaken, bool conditionValue,
|
||||
IfDirective start, int index)
|
||||
{
|
||||
IfDirective start, int index) =>
|
||||
trapFile.WriteTuple("directive_elifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0, start, index);
|
||||
}
|
||||
|
||||
internal static void directive_elses(this TextWriter trapFile, ElseDirective directive, bool branchTaken,
|
||||
IfDirective start, int index)
|
||||
{
|
||||
IfDirective start, int index) =>
|
||||
trapFile.WriteTuple("directive_elses", directive, branchTaken ? 1 : 0, start, index);
|
||||
}
|
||||
|
||||
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive, IfDirective start)
|
||||
{
|
||||
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive, IfDirective start) =>
|
||||
trapFile.WriteTuple("directive_endifs", directive, start);
|
||||
}
|
||||
|
||||
internal static void directive_define_symbols(this TextWriter trapFile, DefineSymbol symb, string name)
|
||||
{
|
||||
internal static void directive_define_symbols(this TextWriter trapFile, DefineSymbol symb, string name) =>
|
||||
trapFile.WriteTuple("directive_define_symbols", symb, name);
|
||||
}
|
||||
|
||||
internal static void locations_mapped(this System.IO.TextWriter trapFile, NonGeneratedSourceLocation l1, Location l2)
|
||||
{
|
||||
internal static void locations_mapped(this System.IO.TextWriter trapFile, NonGeneratedSourceLocation l1, Location l2) =>
|
||||
trapFile.WriteTuple("locations_mapped", l1, l2);
|
||||
}
|
||||
|
||||
internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, int mode)
|
||||
{
|
||||
internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, int mode) =>
|
||||
trapFile.WriteTuple("file_extraction_mode", file, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -0,0 +1 @@
|
||||
## 0.0.7
|
||||
6
csharp/ql/consistency-queries/PrimaryQlClass.ql
Normal file
6
csharp/ql/consistency-queries/PrimaryQlClass.ql
Normal file
@@ -0,0 +1,6 @@
|
||||
import csharp
|
||||
|
||||
query predicate missingPrimaryQlClass(Element e) {
|
||||
not exists(e.getAPrimaryQlClass()) and
|
||||
e.fromSource()
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
1
csharp/ql/lib/change-notes/released/0.0.6.md
Normal file
1
csharp/ql/lib/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.7-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -277,6 +277,8 @@ class TypeParameterConstraints extends Element, @type_parameter_constraints {
|
||||
|
||||
/** Gets a textual representation of these constraints. */
|
||||
override string toString() { result = "where " + this.getTypeParameter().getName() + ": ..." }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeParameterConstraints" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,8 @@ class Modifier extends Element, @modifier {
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Modifier" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,4 +22,6 @@ class Modifier extends Element, @modifier {
|
||||
*/
|
||||
class AccessModifier extends Modifier {
|
||||
AccessModifier() { this.hasName(["public", "private", "internal", "protected"]) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AccessModifier" }
|
||||
}
|
||||
|
||||
@@ -946,17 +946,13 @@ class TryStmt extends Stmt, @try_stmt {
|
||||
exists(ControlFlowElement mid |
|
||||
mid = this.getATriedElement() and
|
||||
not mid instanceof TryStmt and
|
||||
result = getAChild(mid, mid.getEnclosingCallable())
|
||||
result = mid.getAChild() and
|
||||
pragma[only_bind_into](mid.getEnclosingCallable()) =
|
||||
pragma[only_bind_into](result.getEnclosingCallable())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private ControlFlowElement getAChild(ControlFlowElement cfe, Callable c) {
|
||||
result = cfe.getAChild() and
|
||||
c = result.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* A `catch` clause within a `try` statement.
|
||||
*
|
||||
|
||||
@@ -413,6 +413,8 @@ class VoidType extends DotNet::ValueOrRefType, Type, @void_type {
|
||||
final override string getUndecoratedName() { result = "Void" }
|
||||
|
||||
override SystemNamespace getDeclaringNamespace() { any() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "VoidType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -454,6 +456,8 @@ class BoolType extends SimpleType, @bool_type {
|
||||
override string toStringWithTypes() { result = "bool" }
|
||||
|
||||
override int getSize() { result = 1 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BoolType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -467,6 +471,8 @@ class CharType extends SimpleType, @char_type {
|
||||
override int minValue() { result = 0 }
|
||||
|
||||
override int maxValue() { result = 65535 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CharType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -506,6 +512,8 @@ class SByteType extends SignedIntegralType, @sbyte_type {
|
||||
override int minValue() { result = -128 }
|
||||
|
||||
override int maxValue() { result = 127 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SByteType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -519,6 +527,8 @@ class ShortType extends SignedIntegralType, @short_type {
|
||||
override int minValue() { result = -32768 }
|
||||
|
||||
override int maxValue() { result = 32767 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ShortType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -532,6 +542,8 @@ class IntType extends SignedIntegralType, @int_type {
|
||||
override int minValue() { result = -2147483647 - 1 }
|
||||
|
||||
override int maxValue() { result = 2147483647 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "IntType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,6 +553,8 @@ class LongType extends SignedIntegralType, @long_type {
|
||||
override string toStringWithTypes() { result = "long" }
|
||||
|
||||
override int getSize() { result = 8 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LongType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,6 +566,8 @@ class ByteType extends UnsignedIntegralType, @byte_type {
|
||||
override int getSize() { result = 1 }
|
||||
|
||||
override int maxValue() { result = 255 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ByteType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -563,6 +579,8 @@ class UShortType extends UnsignedIntegralType, @ushort_type {
|
||||
override int getSize() { result = 2 }
|
||||
|
||||
override int maxValue() { result = 65535 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UShortType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,6 +590,8 @@ class UIntType extends UnsignedIntegralType, @uint_type {
|
||||
override string toStringWithTypes() { result = "uint" }
|
||||
|
||||
override int getSize() { result = 4 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UIntType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -581,6 +601,8 @@ class ULongType extends UnsignedIntegralType, @ulong_type {
|
||||
override string toStringWithTypes() { result = "ulong" }
|
||||
|
||||
override int getSize() { result = 8 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ULongType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -597,6 +619,8 @@ class FloatType extends FloatingPointType, @float_type {
|
||||
override string toStringWithTypes() { result = "float" }
|
||||
|
||||
override int getSize() { result = 4 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FloatType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -606,6 +630,8 @@ class DoubleType extends FloatingPointType, @double_type {
|
||||
override string toStringWithTypes() { result = "double" }
|
||||
|
||||
override int getSize() { result = 8 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DoubleType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,6 +641,8 @@ class DecimalType extends SimpleType, @decimal_type {
|
||||
override string toStringWithTypes() { result = "decimal" }
|
||||
|
||||
override int getSize() { result = 16 }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DecimalType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -775,6 +803,8 @@ class ObjectType extends Class {
|
||||
ObjectType() { this.hasQualifiedName("System.Object") }
|
||||
|
||||
override string toStringWithTypes() { result = "object" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ObjectType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -784,6 +814,8 @@ class StringType extends Class {
|
||||
StringType() { this.hasQualifiedName("System.String") }
|
||||
|
||||
override string toStringWithTypes() { result = "string" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "StringType" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -910,7 +942,9 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type
|
||||
/**
|
||||
* The `null` type. The type of the `null` literal.
|
||||
*/
|
||||
class NullType extends RefType, @null_type { }
|
||||
class NullType extends RefType, @null_type {
|
||||
override string getAPrimaryQlClass() { result = "NullType" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A nullable type, for example `int?`.
|
||||
@@ -1124,6 +1158,8 @@ class TupleType extends ValueType, @tuple_type {
|
||||
final override predicate hasQualifiedName(string qualifier, string name) {
|
||||
this.getUnderlyingType().hasQualifiedName(qualifier, name)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TupleType" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,6 +36,9 @@ class UsingDirective extends Element, @using_directive {
|
||||
}
|
||||
|
||||
override Location getALocation() { using_directive_location(this, result) }
|
||||
|
||||
/** Holds if this directive is `global`. */
|
||||
predicate isGlobal() { using_global(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -338,6 +338,8 @@ class LocalVariable extends LocalScopeVariable, @local_variable {
|
||||
override Type getType() { localvars(this, _, _, _, getTypeRef(result), _) }
|
||||
|
||||
override Location getALocation() { localvar_location(this, result) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalVariable" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -921,13 +921,15 @@ module Private {
|
||||
|
||||
private predicate inputNeedsReference(string c) {
|
||||
c = "Argument" or
|
||||
parseArg(c, _)
|
||||
parseArg(c, _) or
|
||||
inputNeedsReferenceSpecific(c)
|
||||
}
|
||||
|
||||
private predicate outputNeedsReference(string c) {
|
||||
c = "Argument" or
|
||||
parseArg(c, _) or
|
||||
c = "ReturnValue"
|
||||
c = "ReturnValue" or
|
||||
outputNeedsReferenceSpecific(c)
|
||||
}
|
||||
|
||||
private predicate sourceElementRef(InterpretNode ref, string output, string kind) {
|
||||
|
||||
@@ -171,6 +171,12 @@ string getParameterPositionCsv(ParameterPosition pos) { result = pos.toString()
|
||||
/** Gets the textual representation of an argument position in the format used for flow summaries. */
|
||||
string getArgumentPositionCsv(ArgumentPosition pos) { result = pos.toString() }
|
||||
|
||||
/** Holds if input specification component `c` needs a reference. */
|
||||
predicate inputNeedsReferenceSpecific(string c) { none() }
|
||||
|
||||
/** Holds if output specification component `c` needs a reference. */
|
||||
predicate outputNeedsReferenceSpecific(string c) { none() }
|
||||
|
||||
class SourceOrSinkElement = Element;
|
||||
|
||||
/** Gets the return kind corresponding to specification `"ReturnValue"`. */
|
||||
|
||||
@@ -1084,6 +1084,8 @@ class DiscardExpr extends Expr, @discard_expr {
|
||||
|
||||
private class UnknownExpr extends Expr, @unknown_expr {
|
||||
override string toString() { result = "Expression" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UnknownExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -112,6 +112,8 @@ class SystemBooleanStruct extends BoolType {
|
||||
result.getParameter(1).getType() instanceof BoolType and
|
||||
result.getReturnType() instanceof BoolType
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SystemBooleanStruct" }
|
||||
}
|
||||
|
||||
/** Data flow for `System.Boolean`. */
|
||||
@@ -1092,6 +1094,8 @@ class SystemIntPtrType extends ValueType {
|
||||
this = any(SystemNamespace n).getATypeDeclaration() and
|
||||
this.hasName("IntPtr")
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SystemIntPtrType" }
|
||||
}
|
||||
|
||||
/** The `System.IDisposable` interface. */
|
||||
|
||||
@@ -43,8 +43,15 @@ class Element extends @dotnet_element {
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
|
||||
*
|
||||
* If no primary class can be determined, the result is `"???"`.
|
||||
*/
|
||||
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
||||
final string getPrimaryQlClasses() {
|
||||
result = strictconcat(this.getAPrimaryQlClass(), ",")
|
||||
or
|
||||
not exists(this.getAPrimaryQlClass()) and
|
||||
result = "???"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a primary CodeQL class to which this element belongs.
|
||||
@@ -53,11 +60,12 @@ class Element extends @dotnet_element {
|
||||
* which they belong; for example, `AddExpr` is a primary class, but
|
||||
* `BinaryOperation` is not.
|
||||
*
|
||||
* This predicate always has a result. If no primary class can be
|
||||
* determined, the result is `"???"`. If multiple primary classes match,
|
||||
* this predicate can have multiple results.
|
||||
* If no primary classes match, this predicate has no result. If multiple
|
||||
* primary classes match, this predicate can have multiple results.
|
||||
*
|
||||
* See also `getPrimaryQlClasses`, which is better to use in most cases.
|
||||
*/
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
string getAPrimaryQlClass() { none() }
|
||||
}
|
||||
|
||||
/** An element that has a name. */
|
||||
|
||||
@@ -39,6 +39,8 @@ class Namespace extends Declaration, @namespace {
|
||||
final override string getName() { namespaces(this, result) }
|
||||
|
||||
final override string getUndecoratedName() { namespaces(this, result) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Namespace" }
|
||||
}
|
||||
|
||||
/** The global namespace. */
|
||||
|
||||
@@ -89,4 +89,6 @@ class ArrayType extends ValueOrRefType, @dotnet_array_type {
|
||||
final override string getLabel() { result = this.getElementType().getLabel() + "[]" }
|
||||
|
||||
override string toStringWithTypes() { result = this.getElementType().toStringWithTypes() + "[]" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ArrayType" }
|
||||
}
|
||||
|
||||
@@ -324,6 +324,10 @@ parent_namespace_declaration(
|
||||
|
||||
@using_directive = @using_namespace_directive | @using_static_directive;
|
||||
|
||||
using_global(
|
||||
unique int id: @using_directive ref
|
||||
);
|
||||
|
||||
using_namespace_directives(
|
||||
unique int id: @using_namespace_directive,
|
||||
int namespace_id: @namespace ref);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add 'using_global' relation.
|
||||
compatibility: backwards
|
||||
@@ -1,3 +1,5 @@
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
1
csharp/ql/src/change-notes/released/0.0.6.md
Normal file
1
csharp/ql/src/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.7-dev
|
||||
groups: csharp
|
||||
suites: codeql-suites
|
||||
extractor: csharp
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
global using System;
|
||||
global using System.IO;
|
||||
global using static System.Text.Encoding;
|
||||
9
csharp/ql/test/library-tests/csharp10/global/MyClass1.cs
Normal file
9
csharp/ql/test/library-tests/csharp10/global/MyClass1.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Collections;
|
||||
|
||||
public class MyClass1
|
||||
{
|
||||
public void HelloWorld()
|
||||
{
|
||||
Console.WriteLine("Hello World");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
globalUsing
|
||||
| GlobalUsing.cs:1:1:1:20 | using ...; |
|
||||
| GlobalUsing.cs:2:1:2:23 | using ...; |
|
||||
| GlobalUsing.cs:3:1:3:41 | using static ...; |
|
||||
localUsing
|
||||
| MyClass1.cs:1:1:1:25 | using ...; |
|
||||
globalUsingNamespace
|
||||
| GlobalUsing.cs:1:1:1:20 | using ...; | file://:0:0:0:0 | System |
|
||||
| GlobalUsing.cs:2:1:2:23 | using ...; | file://:0:0:0:0 | System.IO |
|
||||
10
csharp/ql/test/library-tests/csharp10/global/globalUsing.ql
Normal file
10
csharp/ql/test/library-tests/csharp10/global/globalUsing.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import csharp
|
||||
|
||||
query predicate globalUsing(UsingDirective und) { und.isGlobal() }
|
||||
|
||||
query predicate localUsing(UsingDirective ud) { not ud.isGlobal() }
|
||||
|
||||
query predicate globalUsingNamespace(UsingNamespaceDirective und, Namespace namespace) {
|
||||
und.isGlobal() and
|
||||
namespace = und.getImportedNamespace()
|
||||
}
|
||||
86
docs/change-notes.md
Normal file
86
docs/change-notes.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Adding change notes for query and library changes
|
||||
|
||||
Each CodeQL query pack or library pack has its own change log to track how that pack changes with each release. Any non-trivial, user-visible change to a query or library should add a change note to the affected pack. This document describes how to do that.
|
||||
|
||||
## Creating a change note
|
||||
To create a new change note for a pack, create a new markdown file in the `change-notes` directory of the pack (e.g., in `cpp/ql/src/change-notes` for the C++ standard query pack). The markdown file must be named `YYYY-MM-DD-id.md`, where `YYYY-MM-DD` is the date of the change, and `id` is a short string to help identify the change. For example, if you were adding a new integer overflow query to the C++ standard query pack, you might do so from a branch named `int-overflow-query`, with a change note file named `cpp/ql/src/change-notes/2021-12-14-int-overflow-query.md`. Here are a few example change note files:
|
||||
|
||||
```yaml
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new query, `cpp/integer-overflow`, to detect code that depends on the result of signed integer overflow.
|
||||
```
|
||||
|
||||
```yaml
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixed a performance issue where the `cpp/integer-overflow` query would time out on large databases.
|
||||
```
|
||||
|
||||
```yaml
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added taint flow model for `std::codecvt`.
|
||||
```
|
||||
|
||||
```yaml
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added taint flow model for `std::string`.
|
||||
```
|
||||
|
||||
### Metadata
|
||||
The change note file requires some metadata at the beginning of the file. This metadata is later used to determine how to advance the version number of the pack next time it is published, and to group related change notes in the final changelog. The metadata is YAML, enclosed by a `---` line before and after.
|
||||
|
||||
The valid YAML properties in the metadata are:
|
||||
|
||||
- `category` - Required. This is a string that identifies one of a fixed set of categories that the change falls into. In the full changelog for the pack, the change notes for a particular release will be grouped together by category. The category also determines how this change will affect the version number of the pack's next release. For more information on available categories, see the Change Categories section below.
|
||||
- `tags` - Optional. A list of string tags. These are not currently used by the change note infrastructure, so just omit this property.
|
||||
|
||||
### Description
|
||||
After the `---` line following the metadata, the rest of the markdown file is the user-visible content of the change note. This should usually be a single markdown bullet list entry (starting with `*`), although it is acceptable to have multiple bullet entries in the same change note if there are multiple changes that are closely related and have the same category metadata.
|
||||
|
||||
## Change categories
|
||||
Each change note must specifiy a `category` property in its metadata. This category servers two purposes: It determines how the change affects the version number of the next release of the pack, and it is used to group related changes in the final changelog. There is one set of available categories for query packs, and another set of available categories for library packs.
|
||||
|
||||
### Query pack change categories
|
||||
| Category | SemVer effect | Description |
|
||||
|----------------|--------------------|-------------|
|
||||
| breaking | major version bump | Any breaking change to the query pack, the most common of which is the deletion of an existing query. |
|
||||
| deprecated | minor version bump | An existing query has been marked as `deprecated`. |
|
||||
| newQuery | minor version bump | A new query has been added. |
|
||||
| queryMetadata | minor version bump | The metadata of a query has been changed (e.g., to increase or reduce the `@precision`). |
|
||||
| majorAnalysis | minor version bump | The set of results produced by a query has changed (fewer false positives, more true positives, etc.) enough to be noticed by users of the query pack. |
|
||||
| minorAnalysis | patch version bump | The set of results produced by a query has changed, but only in scenarios that affect relatively few users. |
|
||||
| fix | patch version bump | A fix that does not change the results reported by a query (e.g., a performance fix). |
|
||||
|
||||
### Library pack change categories
|
||||
| Category | SemVer effect | Description |
|
||||
|----------------|--------------------|-------------|
|
||||
| breaking | major version bump | Any breaking change to the library pack, the most common of which is the deletion of an existing API. |
|
||||
| deprecated | minor version bump | An existing API has been marked as `deprecated`. |
|
||||
| feature | minor version bump | A new library API has been added. |
|
||||
| majorAnalysis | minor version bump | An API has changed in a way that may affect the results produced by a query that consumes the API. |
|
||||
| minorAnalysis | patch version bump | An API has changed in a way that may affect the results produced by a query that consumes the API, but only in scenarios that affect relatively few users. |
|
||||
| fix | patch version bump | An API has been fixed in a way that is not likely to affect the results produced by a query that consumes the API. |
|
||||
|
||||
## How the final changelog is created
|
||||
When a new release of a pack is published, the publishing process consolidates all of the change note files from that pack's `change-notes` directory into the pack's `CHANGELOG.md` file. The consolidation process does the following:
|
||||
|
||||
- Strips all metadata from each change note.
|
||||
- Strips all leading and trailing blank lines from the description of each change note.
|
||||
- Adds a newline at the end of the description of any change note that does not already end with a newline.
|
||||
- Groups change notes by category.
|
||||
- Adds a section to the changelog for each category that contains at least one change note. The section consists of a section heading followed by the contents of each change note in that category.
|
||||
- Deletes the individual change note files.
|
||||
|
||||
## How change notes affect the version of the pack
|
||||
When a new release of a pack is published, the pack's version number is advanced based on the categories of the changes in that version:
|
||||
- If any change note has a SemVer effect of `major version bump`, then the version number's major component will be incremented (e.g., `1.4.5` -> `2.0.0`).
|
||||
- Otherwise, if any change note has a SemVer effect of `minor version bump`, then the version number's minor component will be incremented (e.g., `1.4.5` -> `1.5.0`).
|
||||
- Otherwise, the version number's patch component will be incremented (e.g., `1.4.5` -> `1.4.6`).
|
||||
Thus, it is important to choose the correct category for each change note, so that users can rely on the pack's version number to indicate compatibility with previous versions of the pack.
|
||||
@@ -1,111 +1,111 @@
|
||||
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
|
||||
android.app,7,,84,,,,,,7,,,,,,,,,,,,,,,,,13,71
|
||||
android.content,24,27,96,,,,,,16,,,,,,,,,8,,,,,,27,,31,65
|
||||
android.database,59,,30,,,,,,,,,,,,,,,59,,,,,,,,30,
|
||||
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,45,15
|
||||
android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,41,81
|
||||
android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,16,,
|
||||
android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,3,,2,,
|
||||
androidx.slice,,5,88,,,,,,,,,,,,,,,,,,,,,5,,27,61
|
||||
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,62,23
|
||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,17
|
||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,2,551
|
||||
com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,
|
||||
com.google.common.io,6,,73,,,,,,,,,,,,,,,,6,,,,,,,72,1
|
||||
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,
|
||||
com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,
|
||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,
|
||||
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,2,,7,,
|
||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,
|
||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,2,,,,,,94,55
|
||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
java.io,3,,31,,3,,,,,,,,,,,,,,,,,,,,,30,1
|
||||
java.lang,8,,56,,,,,,,,,,8,,,,,,,,,,,,,45,11
|
||||
java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,3,7,
|
||||
java.nio,10,,4,,10,,,,,,,,,,,,,,,,,,,,,4,
|
||||
java.sql,7,,,,,,,,,,,,,,,,,7,,,,,,,,,
|
||||
java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,16,414
|
||||
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,2,,7,,
|
||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,
|
||||
javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,
|
||||
javax.net.ssl,2,,,,,,,,,,,,,,,,2,,,,,,,,,,
|
||||
javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,21,2,
|
||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,1,,
|
||||
javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,
|
||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,2,,,,,,94,55
|
||||
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,1,,,,6,
|
||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,3,,,,,,
|
||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,5,,,,,
|
||||
ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,
|
||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,22,
|
||||
org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,293,131
|
||||
org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,
|
||||
org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,
|
||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,220,52
|
||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,1,,2,39,
|
||||
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,2,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,2,,3,62,8
|
||||
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,6,,,,,,,,,
|
||||
org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,
|
||||
org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,4,4
|
||||
org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,
|
||||
org.dom4j,20,,,,,,,,,,,,,,,,,,,,20,,,,,,
|
||||
org.hibernate,7,,,,,,,,,,,,,,,,,7,,,,,,,,,
|
||||
org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,
|
||||
org.jooq,1,,,,,,,,,,,,,,,,,1,,,,,,,,,
|
||||
org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,198,38
|
||||
org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,
|
||||
org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,
|
||||
org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,2,4
|
||||
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,26
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,60,10
|
||||
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,10,,,,,,,,,
|
||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,9,,,,,,,,,
|
||||
org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,87,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,12,13,
|
||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,
|
||||
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,138,25
|
||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,4,,
|
||||
ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,48
|
||||
ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
|
||||
android.app,7,,84,,,,,,7,,,,,,,,,,,,,,,,,,13,71
|
||||
android.content,24,27,96,,,,,,16,,,,,,,,,8,,,,,,,27,,31,65
|
||||
android.database,59,,30,,,,,,,,,,,,,,,59,,,,,,,,,30,
|
||||
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,45,15
|
||||
android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,41,81
|
||||
android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,16,,
|
||||
android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,3,,2,,
|
||||
androidx.slice,,5,88,,,,,,,,,,,,,,,,,,,,,,5,,27,61
|
||||
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,62,23
|
||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,17
|
||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,2,551
|
||||
com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,
|
||||
com.google.common.io,6,,73,,,,,,,,,,,,,,,,6,,,,,,,,72,1
|
||||
com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,
|
||||
com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,
|
||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,
|
||||
jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,,
|
||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,
|
||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,2,,,,,,,94,55
|
||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
java.io,37,,31,,15,,,,,,,,,,,,,,,,22,,,,,,30,1
|
||||
java.lang,8,,56,,,,,,,,,,8,,,,,,,,,,,,,,45,11
|
||||
java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,3,7,
|
||||
java.nio,15,,4,,13,,,,,,,,,,,,,,,,2,,,,,,4,
|
||||
java.sql,7,,,,,,,,,,,,,,,,,7,,,,,,,,,,
|
||||
java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,16,414
|
||||
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,,
|
||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,
|
||||
javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,
|
||||
javax.net.ssl,2,,,,,,,,,,,,,,,,2,,,,,,,,,,,
|
||||
javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,
|
||||
javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,21,2,
|
||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,1,,
|
||||
javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,
|
||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,2,,,,,,,94,55
|
||||
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,1,,,,6,
|
||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,3,,,,,,
|
||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,5,,,,,
|
||||
ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,
|
||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,,22,
|
||||
org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,293,131
|
||||
org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,
|
||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,220,52
|
||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,1,,2,39,
|
||||
org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,2,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,2,,3,62,8
|
||||
org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,6,,,,,,,,,,
|
||||
org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,
|
||||
org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,4,4
|
||||
org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,
|
||||
org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.dom4j,20,,,,,,,,,,,,,,,,,,,,,20,,,,,,
|
||||
org.hibernate,7,,,,,,,,,,,,,,,,,7,,,,,,,,,,
|
||||
org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,
|
||||
org.jooq,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,
|
||||
org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,198,38
|
||||
org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,
|
||||
org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,
|
||||
org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,2,4
|
||||
org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,26
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,60,10
|
||||
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,10,,,,,,,,,,
|
||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,9,,,,,,,,,,
|
||||
org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,
|
||||
org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,87,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,12,13,
|
||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,138,25
|
||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,4,,
|
||||
ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,48
|
||||
ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
|
||||
|
@@ -15,9 +15,9 @@ Java framework & library support
|
||||
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
|
||||
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,35,,6,,,,,
|
||||
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
|
||||
Java Standard Library,``java.*``,3,529,72,13,,,7,,,10
|
||||
Java Standard Library,``java.*``,3,529,111,28,,,7,,,10
|
||||
Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,29,472,91,,,,19,14,,29
|
||||
Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,919,,,,14,18,,
|
||||
Totals,,180,5646,1276,13,6,10,107,33,1,66
|
||||
Totals,,180,5646,1315,28,6,10,107,33,1,66
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 0.0.6
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Data flow now propagates taint from remote source `Parameter` types to read steps of their fields (e.g. `tainted.publicField` or `tainted.getField()`). This also applies to their subtypes and the types of their fields, recursively.
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
## 0.0.6
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Data flow now propagates taint from remote source `Parameter` types to read steps of their fields (e.g. `tainted.publicField` or `tainted.getField()`). This also applies to their subtypes and the types of their fields, recursively.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-all
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.7-dev
|
||||
groups: java
|
||||
dbscheme: config/semmlecode.dbscheme
|
||||
extractor: java
|
||||
|
||||
@@ -115,6 +115,7 @@ private module Frameworks {
|
||||
private import semmle.code.java.security.AndroidIntentRedirection
|
||||
private import semmle.code.java.security.ResponseSplitting
|
||||
private import semmle.code.java.security.InformationLeak
|
||||
private import semmle.code.java.security.Files
|
||||
private import semmle.code.java.security.GroovyInjection
|
||||
private import semmle.code.java.security.ImplicitPendingIntents
|
||||
private import semmle.code.java.security.JexlInjectionSinkModels
|
||||
@@ -259,20 +260,6 @@ private predicate sinkModelCsv(string row) {
|
||||
"java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader);;Argument[1];open-url",
|
||||
"java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader,URLStreamHandlerFactory);;Argument[1];open-url",
|
||||
"java.net;URLClassLoader;false;newInstance;;;Argument[0];open-url",
|
||||
// Create file
|
||||
"java.io;FileOutputStream;false;FileOutputStream;;;Argument[0];create-file",
|
||||
"java.io;RandomAccessFile;false;RandomAccessFile;;;Argument[0];create-file",
|
||||
"java.io;FileWriter;false;FileWriter;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;move;;;Argument[1];create-file",
|
||||
"java.nio.file;Files;false;copy;;;Argument[1];create-file",
|
||||
"java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;newBufferedReader;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createDirectory;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createFile;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createLink;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createSymbolicLink;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createTempDirectory;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createTempFile;;;Argument[0];create-file",
|
||||
// Bean validation
|
||||
"javax.validation;ConstraintValidatorContext;true;buildConstraintViolationWithTemplate;;;Argument[0];bean-validation",
|
||||
// Set hostname
|
||||
|
||||
@@ -921,13 +921,15 @@ module Private {
|
||||
|
||||
private predicate inputNeedsReference(string c) {
|
||||
c = "Argument" or
|
||||
parseArg(c, _)
|
||||
parseArg(c, _) or
|
||||
inputNeedsReferenceSpecific(c)
|
||||
}
|
||||
|
||||
private predicate outputNeedsReference(string c) {
|
||||
c = "Argument" or
|
||||
parseArg(c, _) or
|
||||
c = "ReturnValue"
|
||||
c = "ReturnValue" or
|
||||
outputNeedsReferenceSpecific(c)
|
||||
}
|
||||
|
||||
private predicate sourceElementRef(InterpretNode ref, string output, string kind) {
|
||||
|
||||
@@ -102,6 +102,12 @@ string getParameterPositionCsv(ParameterPosition pos) { result = pos.toString()
|
||||
/** Gets the textual representation of an argument position in the format used for flow summaries. */
|
||||
string getArgumentPositionCsv(ArgumentPosition pos) { result = pos.toString() }
|
||||
|
||||
/** Holds if input specification component `c` needs a reference. */
|
||||
predicate inputNeedsReferenceSpecific(string c) { none() }
|
||||
|
||||
/** Holds if output specification component `c` needs a reference. */
|
||||
predicate outputNeedsReferenceSpecific(string c) { none() }
|
||||
|
||||
class SourceOrSinkElement = Top;
|
||||
|
||||
/**
|
||||
|
||||
16
java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
Normal file
16
java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
Normal file
@@ -0,0 +1,16 @@
|
||||
/** Provides classes and predicates to track Android fragments. */
|
||||
|
||||
import java
|
||||
|
||||
/** The class `android.app.Fragment` */
|
||||
class Fragment extends Class {
|
||||
Fragment() { this.hasQualifiedName("android.app", "Fragment") }
|
||||
}
|
||||
|
||||
/** The method `instantiate` of the class `android.app.Fragment`. */
|
||||
class FragmentInstantiateMethod extends Method {
|
||||
FragmentInstantiateMethod() {
|
||||
this.getDeclaringType() instanceof Fragment and
|
||||
this.hasName("instantiate")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Provides classes and predicates to reason about cleartext storage in the Android filesystem
|
||||
* (external or internal storage).
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
import semmle.code.java.security.CleartextStorageQuery
|
||||
import semmle.code.java.security.Files
|
||||
import semmle.code.xml.AndroidManifest
|
||||
|
||||
private class AndroidFilesystemCleartextStorageSink extends CleartextStorageSink {
|
||||
AndroidFilesystemCleartextStorageSink() {
|
||||
filesystemInput(_, this.asExpr()) and
|
||||
// Make sure we are in an Android application.
|
||||
exists(AndroidManifestXmlFile manifest)
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to a method or constructor that may write to files to the local filesystem. */
|
||||
class LocalFileOpenCall extends Storable {
|
||||
LocalFileOpenCall() {
|
||||
this = any(DataFlow::Node sink | sinkNode(sink, "create-file")).asExpr().(Argument).getCall()
|
||||
}
|
||||
|
||||
override Expr getAnInput() {
|
||||
exists(FilesystemFlowConfig conf, DataFlow::Node n |
|
||||
filesystemInput(n, result) and
|
||||
conf.hasFlow(DataFlow::exprNode(this), n)
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getAStore() {
|
||||
exists(FilesystemFlowConfig conf, DataFlow::Node n |
|
||||
closesFile(n, result) and
|
||||
conf.hasFlow(DataFlow::exprNode(this), n)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `input` is written into `file`. */
|
||||
private predicate filesystemInput(DataFlow::Node file, Argument input) {
|
||||
exists(DataFlow::Node write | sinkNode(write, "write-file") |
|
||||
input = write.asExpr() or
|
||||
isVarargs(input, write)
|
||||
) and
|
||||
if input.getCall().getCallee().isStatic()
|
||||
then file.asExpr() = input.getCall()
|
||||
else file.asExpr() = input.getCall().getQualifier()
|
||||
}
|
||||
|
||||
/** Holds if `arg` is part of `varargs`. */
|
||||
private predicate isVarargs(Argument arg, DataFlow::ImplicitVarargsArray varargs) {
|
||||
arg.isVararg() and arg.getCall() = varargs.getCall()
|
||||
}
|
||||
|
||||
/** Holds if `store` closes `file`. */
|
||||
private predicate closesFile(DataFlow::Node file, Call closeCall) {
|
||||
closeCall.getCallee() instanceof CloseFileMethod and
|
||||
if closeCall.getCallee().isStatic()
|
||||
then file.asExpr() = closeCall
|
||||
else file.asExpr() = closeCall.getQualifier()
|
||||
or
|
||||
// try-with-resources automatically closes the file
|
||||
any(TryStmt try).getAResource() = closeCall.(LocalFileOpenCall).getEnclosingStmt() and
|
||||
closeCall = file.asExpr()
|
||||
}
|
||||
|
||||
/** A method that closes a file, perhaps after writing some data. */
|
||||
private class CloseFileMethod extends Method {
|
||||
CloseFileMethod() {
|
||||
this.hasQualifiedName("java.io", ["RandomAccessFile", "FileOutputStream", "PrintStream"],
|
||||
"close")
|
||||
or
|
||||
this.getDeclaringType().getASupertype*().hasQualifiedName("java.io", "Writer") and
|
||||
this.hasName("close")
|
||||
or
|
||||
this.hasQualifiedName("java.nio.file", "Files", ["write", "writeString"])
|
||||
}
|
||||
}
|
||||
|
||||
private class FilesystemFlowConfig extends DataFlow::Configuration {
|
||||
FilesystemFlowConfig() { this = "FilesystemFlowConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
filesystemInput(sink, _) or
|
||||
closesFile(sink, _)
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// Add nested Writer constructors as extra data flow steps
|
||||
exists(ClassInstanceExpr cie |
|
||||
cie.getConstructedType().getASupertype*().hasQualifiedName("java.io", "Writer") and
|
||||
node1.asExpr() = cie.getArgument(0) and
|
||||
node2.asExpr() = cie
|
||||
)
|
||||
}
|
||||
}
|
||||
72
java/ql/lib/semmle/code/java/security/Files.qll
Normal file
72
java/ql/lib/semmle/code/java/security/Files.qll
Normal file
@@ -0,0 +1,72 @@
|
||||
/** Provides classes and predicates to work with File objects. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
private class CreateFileSinkModels extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"java.io;FileOutputStream;false;FileOutputStream;;;Argument[0];create-file",
|
||||
"java.io;RandomAccessFile;false;RandomAccessFile;;;Argument[0];create-file",
|
||||
"java.io;FileWriter;false;FileWriter;;;Argument[0];create-file",
|
||||
"java.io;PrintStream;false;PrintStream;(File);;Argument[0];create-file",
|
||||
"java.io;PrintStream;false;PrintStream;(File,String);;Argument[0];create-file",
|
||||
"java.io;PrintStream;false;PrintStream;(File,Charset);;Argument[0];create-file",
|
||||
"java.io;PrintStream;false;PrintStream;(String);;Argument[0];create-file",
|
||||
"java.io;PrintStream;false;PrintStream;(String,String);;Argument[0];create-file",
|
||||
"java.io;PrintStream;false;PrintStream;(String,Charset);;Argument[0];create-file",
|
||||
"java.io;PrintWriter;false;PrintWriter;(File);;Argument[0];create-file",
|
||||
"java.io;PrintWriter;false;PrintWriter;(File,String);;Argument[0];create-file",
|
||||
"java.io;PrintWriter;false;PrintWriter;(File,Charset);;Argument[0];create-file",
|
||||
"java.io;PrintWriter;false;PrintWriter;(String);;Argument[0];create-file",
|
||||
"java.io;PrintWriter;false;PrintWriter;(String,String);;Argument[0];create-file",
|
||||
"java.io;PrintWriter;false;PrintWriter;(String,Charset);;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;copy;;;Argument[1];create-file",
|
||||
"java.nio.file;Files;false;createDirectories;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createDirectory;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createFile;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createLink;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createSymbolicLink;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createTempDirectory;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;createTempFile;(Path,String,String,FileAttribute[]);;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;move;;;Argument[1];create-file",
|
||||
"java.nio.file;Files;false;newBufferedWriter;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;write;;;Argument[0];create-file",
|
||||
"java.nio.file;Files;false;writeString;;;Argument[0];create-file"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class WriteFileSinkModels extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"java.io;FileOutputStream;false;write;;;Argument[0];write-file",
|
||||
"java.io;RandomAccessFile;false;write;;;Argument[0];write-file",
|
||||
"java.io;RandomAccessFile;false;writeBytes;;;Argument[0];write-file",
|
||||
"java.io;RandomAccessFile;false;writeChars;;;Argument[0];write-file",
|
||||
"java.io;RandomAccessFile;false;writeUTF;;;Argument[0];write-file",
|
||||
"java.io;Writer;true;append;;;Argument[0];write-file",
|
||||
"java.io;Writer;true;write;;;Argument[0];write-file",
|
||||
"java.io;PrintStream;true;append;;;Argument[0];write-file",
|
||||
"java.io;PrintStream;true;format;(String,Object[]);;Argument[0..1];write-file",
|
||||
"java.io;PrintStream;true;format;(Locale,String,Object[]);;Argument[1..2];write-file",
|
||||
"java.io;PrintStream;true;print;;;Argument[0];write-file",
|
||||
"java.io;PrintStream;true;printf;(String,Object[]);;Argument[0..1];write-file",
|
||||
"java.io;PrintStream;true;printf;(Locale,String,Object[]);;Argument[1..2];write-file",
|
||||
"java.io;PrintStream;true;println;;;Argument[0];write-file",
|
||||
"java.io;PrintStream;true;write;;;Argument[0];write-file",
|
||||
"java.io;PrintStream;true;writeBytes;;;Argument[0];write-file",
|
||||
"java.io;PrintWriter;false;format;(String,Object[]);;Argument[0..1];write-file",
|
||||
"java.io;PrintWriter;false;format;(Locale,String,Object[]);;Argument[1..2];write-file",
|
||||
"java.io;PrintWriter;false;print;;;Argument[0];write-file",
|
||||
"java.io;PrintWriter;false;printf;(String,Object[]);;Argument[0..1];write-file",
|
||||
"java.io;PrintWriter;false;printf;(Locale,String,Object[]);;Argument[1..2];write-file",
|
||||
"java.io;PrintWriter;false;println;;;Argument[0];write-file",
|
||||
"java.nio.file;Files;false;write;;;Argument[1];write-file",
|
||||
"java.nio.file;Files;false;writeString;;;Argument[1];write-file"
|
||||
]
|
||||
}
|
||||
}
|
||||
83
java/ql/lib/semmle/code/java/security/FragmentInjection.qll
Normal file
83
java/ql/lib/semmle/code/java/security/FragmentInjection.qll
Normal file
@@ -0,0 +1,83 @@
|
||||
/** Provides classes and predicates to reason about Android Fragment injection vulnerabilities. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.frameworks.android.Android
|
||||
private import semmle.code.java.frameworks.android.Fragment
|
||||
private import semmle.code.java.Reflection
|
||||
|
||||
/** The method `isValidFragment` of the class `android.preference.PreferenceActivity`. */
|
||||
class IsValidFragmentMethod extends Method {
|
||||
IsValidFragmentMethod() {
|
||||
this.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.hasQualifiedName("android.preference", "PreferenceActivity") and
|
||||
this.hasName("isValidFragment")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this method makes the Activity it is declared in vulnerable to Fragment injection,
|
||||
* that is, all code paths in this method return `true` and the Activity is exported.
|
||||
*/
|
||||
predicate isUnsafe() {
|
||||
this.getDeclaringType().(AndroidActivity).isExported() and
|
||||
forex(ReturnStmt retStmt | retStmt.getEnclosingCallable() = this |
|
||||
retStmt.getResult().(BooleanLiteral).getBooleanValue() = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink for Fragment injection vulnerabilities,
|
||||
* that is, method calls that dynamically add fragments to activities.
|
||||
*/
|
||||
abstract class FragmentInjectionSink extends DataFlow::Node { }
|
||||
|
||||
/** An additional taint step for flows related to Fragment injection vulnerabilites. */
|
||||
class FragmentInjectionAdditionalTaintStep extends Unit {
|
||||
/**
|
||||
* Holds if the step from `node1` to `node2` should be considered a taint
|
||||
* step in flows related to Fragment injection vulnerabilites.
|
||||
*/
|
||||
abstract predicate step(DataFlow::Node n1, DataFlow::Node n2);
|
||||
}
|
||||
|
||||
private class FragmentInjectionSinkModels extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
["android.app", "android.support.v4.app", "androidx.fragment.app"] +
|
||||
";FragmentTransaction;true;" +
|
||||
[
|
||||
"add;(Class,Bundle,String);;Argument[0]", "add;(Fragment,String);;Argument[0]",
|
||||
"add;(int,Class,Bundle);;Argument[1]", "add;(int,Fragment);;Argument[1]",
|
||||
"add;(int,Class,Bundle,String);;Argument[1]", "add;(int,Fragment,String);;Argument[1]",
|
||||
"attach;(Fragment);;Argument[0]", "replace;(int,Class,Bundle);;Argument[1]",
|
||||
"replace;(int,Fragment);;Argument[1]", "replace;(int,Class,Bundle,String);;Argument[1]",
|
||||
"replace;(int,Fragment,String);;Argument[1]",
|
||||
] + ";fragment-injection"
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultFragmentInjectionSink extends FragmentInjectionSink {
|
||||
DefaultFragmentInjectionSink() { sinkNode(this, "fragment-injection") }
|
||||
}
|
||||
|
||||
private class DefaultFragmentInjectionAdditionalTaintStep extends FragmentInjectionAdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(ReflectiveClassIdentifierMethodAccess ma |
|
||||
ma.getArgument(0) = n1.asExpr() and ma = n2.asExpr()
|
||||
)
|
||||
or
|
||||
exists(NewInstance ni |
|
||||
ni.getQualifier() = n1.asExpr() and
|
||||
ni = n2.asExpr()
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof FragmentInstantiateMethod and
|
||||
ma.getArgument(1) = n1.asExpr() and
|
||||
ma = n2.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/** Provides classes and predicates to be used in queries related to Android Fragment injection. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.security.FragmentInjection
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to create Android fragments dynamically.
|
||||
*/
|
||||
class FragmentInjectionTaintConf extends TaintTracking::Configuration {
|
||||
FragmentInjectionTaintConf() { this = "FragmentInjectionTaintConf" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof FragmentInjectionSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
any(FragmentInjectionAdditionalTaintStep c).step(n1, n2)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Provides clases and methods shared by randomness-related queries. */
|
||||
/** Provides classes and methods shared by randomness-related queries. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.DefUse
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
public void fileSystemStorageUnsafe(String name, String password) {
|
||||
// BAD - sensitive data stored in cleartext
|
||||
FileWriter fw = new FileWriter("some_file.txt");
|
||||
fw.write(name + ":" + password);
|
||||
fw.close();
|
||||
}
|
||||
|
||||
public void filesystemStorageEncryptedFileSafe(Context context, String name, String password) {
|
||||
// GOOD - the whole file is encrypted with androidx.security.crypto.EncryptedFile
|
||||
File file = new File("some_file.txt");
|
||||
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
|
||||
EncryptedFile encryptedFile = new EncryptedFile.Builder(
|
||||
file,
|
||||
context,
|
||||
masterKeyAlias,
|
||||
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
|
||||
).build();
|
||||
FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();
|
||||
encryptedOutputStream.write(name + ":" + password);
|
||||
}
|
||||
|
||||
public void fileSystemStorageSafe(String name, String password) {
|
||||
// GOOD - sensitive data is encrypted using a custom method
|
||||
FileWriter fw = new FileWriter("some_file.txt");
|
||||
fw.write(name + ":" + encrypt(password));
|
||||
fw.close();
|
||||
}
|
||||
|
||||
private static String encrypt(String cleartext) {
|
||||
// Use an encryption or strong hashing algorithm in the real world.
|
||||
// The example below just returns a SHA-256 hash.
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
|
||||
String encoded = Base64.getEncoder().encodeToString(hash);
|
||||
return encoded;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Android applications with the appropriate permissions can write files either to the device external storage or the application internal storage, depending on the application's needs. However, sensitive information should not be saved in cleartext. Otherwise it can be accessed by any process or user in rooted devices, or can be disclosed through chained vulnerabilities, like unexpected access to the private storage through exposed components.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Consider using the <code>EncryptedFile</code> class to work with files containing sensitive data. Alternatively, use encryption algorithms to encrypt the sensitive data being stored.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the first example, sensitive user information is stored in cleartext using a local file.
|
||||
</p>
|
||||
<p>
|
||||
In the second and third examples, the code encrypts sensitive information before saving it to the filesystem.
|
||||
</p>
|
||||
<sample src="CleartextStorageAndroidFilesystem.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Android Developers:
|
||||
<a href="https://developer.android.com/topic/security/data">Work with data more securely</a>
|
||||
</li>
|
||||
<li>
|
||||
Android Developers:
|
||||
<a href="https://developer.android.com/reference/androidx/security/crypto/EncryptedFile">EncryptedFile</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Cleartext storage of sensitive information in the Android filesystem
|
||||
* @description Cleartext storage of sensitive information in the Android filesystem
|
||||
* allows access for users with root privileges or unexpected exposure
|
||||
* from chained vulnerabilities.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @id java/android/cleartext-storage-filesystem
|
||||
* @tags security
|
||||
* external/cwe/cwe-312
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
|
||||
|
||||
from SensitiveSource data, LocalFileOpenCall s, Expr input, Expr store
|
||||
where
|
||||
input = s.getAnInput() and
|
||||
store = s.getAStore() and
|
||||
data.flowsTo(input)
|
||||
select store, "Local file $@ containing $@ is stored $@. Data was added $@.", s, s.toString(), data,
|
||||
"sensitive data", store, "here", input, "here"
|
||||
60
java/ql/src/Security/CWE/CWE-470/FragmentInjection.inc.qhelp
Normal file
60
java/ql/src/Security/CWE/CWE-470/FragmentInjection.inc.qhelp
Normal file
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
When fragments are instantiated with externally provided names, this exposes any exported activity that dynamically
|
||||
creates and hosts the fragment to fragment injection. A malicious application could provide the
|
||||
name of an arbitrary fragment, even one not designed to be externally accessible, and inject it into the activity.
|
||||
This can bypass access controls and expose the application to unintended effects.
|
||||
</p>
|
||||
<p>
|
||||
Fragments are reusable parts of an Android application's user interface.
|
||||
Even though a fragment controls its own lifecycle and layout, and handles its input events,
|
||||
it cannot exist on its own: it must be hosted either by an activity or another fragment.
|
||||
This means that, normally, a fragment will be accessible by third-party applications (that is, exported)
|
||||
only if its hosting activity is itself exported.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
In general, do not instantiate classes (including fragments) with user-provided names
|
||||
unless the name has been properly validated.
|
||||
|
||||
Also, if an exported activity is extending the <code>PreferenceActivity</code> class, make sure that
|
||||
the <code>isValidFragment</code> method is overriden and only returns <code>true</code> when the provided
|
||||
<code>fragmentName</code> points to an intended fragment.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows two cases: in the first one, untrusted data is used to instantiate and
|
||||
add a fragment to an activity, while in the second one, a fragment is safely added with a static name.
|
||||
</p>
|
||||
<sample src="FragmentInjection.java" />
|
||||
|
||||
<p>
|
||||
The next example shows two activities that extend <code>PreferenceActivity</code>. The first activity overrides
|
||||
<code>isValidFragment</code>, but it wrongly returns <code>true</code> unconditionally. The second activity
|
||||
correctly overrides <code>isValidFragment</code> so that it only returns <code>true</code> when <code>fragmentName</code>
|
||||
is a trusted fragment name.
|
||||
</p>
|
||||
<sample src="FragmentInjectionInPreferenceActivity.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li> Google Help:
|
||||
<a href="https://support.google.com/faqs/answer/7188427?hl=en">How to fix Fragment Injection vulnerability</a>.
|
||||
</li>
|
||||
<li>
|
||||
IBM Security Systems:
|
||||
<a href="https://securityintelligence.com/wp-content/uploads/2013/12/android-collapses-into-fragments.pdf">Android collapses into Fragments</a>.
|
||||
</li>
|
||||
<li>
|
||||
Android Developers:
|
||||
<a href="https://developer.android.com/guide/fragments">Fragments</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
22
java/ql/src/Security/CWE/CWE-470/FragmentInjection.java
Normal file
22
java/ql/src/Security/CWE/CWE-470/FragmentInjection.java
Normal file
@@ -0,0 +1,22 @@
|
||||
public class MyActivity extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstance) {
|
||||
try {
|
||||
super.onCreate(savedInstance);
|
||||
// BAD: Fragment instantiated from user input without validation
|
||||
{
|
||||
String fName = getIntent().getStringExtra("fragmentName");
|
||||
getFragmentManager().beginTransaction().replace(com.android.internal.R.id.prefs,
|
||||
Fragment.instantiate(this, fName, null)).commit();
|
||||
}
|
||||
// GOOD: Fragment instantiated statically
|
||||
{
|
||||
getFragmentManager().beginTransaction()
|
||||
.replace(com.android.internal.R.id.prefs, new MyFragment()).commit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
4
java/ql/src/Security/CWE/CWE-470/FragmentInjection.qhelp
Normal file
4
java/ql/src/Security/CWE/CWE-470/FragmentInjection.qhelp
Normal file
@@ -0,0 +1,4 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="FragmentInjection.inc.qhelp"></include>
|
||||
</qhelp>
|
||||
21
java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql
Normal file
21
java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @name Android fragment injection
|
||||
* @description Instantiating an Android fragment from a user-provided value
|
||||
* may allow a malicious application to bypass access controls, exposing the application to unintended effects.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/android/fragment-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-470
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.FragmentInjectionQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where any(FragmentInjectionTaintConf conf).hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Fragment injection from $@.", source.getNode(),
|
||||
"this user input"
|
||||
@@ -0,0 +1,21 @@
|
||||
class UnsafeActivity extends PreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected boolean isValidFragment(String fragmentName) {
|
||||
// BAD: any Fragment name can be provided.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SafeActivity extends PreferenceActivity {
|
||||
@Override
|
||||
protected boolean isValidFragment(String fragmentName) {
|
||||
// Good: only trusted Fragment names are allowed.
|
||||
return SafeFragment1.class.getName().equals(fragmentName)
|
||||
|| SafeFragment2.class.getName().equals(fragmentName)
|
||||
|| SafeFragment3.class.getName().equals(fragmentName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="FragmentInjection.inc.qhelp"></include>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Android fragment injection in PreferenceActivity
|
||||
* @description An insecure implementation of the 'isValidFragment' method
|
||||
* of the 'PreferenceActivity' class may allow a malicious application to bypass access controls,
|
||||
* exposing the application to unintended effects.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/android/fragment-injection-preference-activity
|
||||
* @tags security
|
||||
* external/cwe/cwe-470
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.FragmentInjection
|
||||
|
||||
from IsValidFragmentMethod m
|
||||
where m.isUnsafe()
|
||||
select m,
|
||||
"The 'isValidFragment' method always returns true. This makes the exported Activity $@ vulnerable to Fragment Injection.",
|
||||
m.getDeclaringType(), m.getDeclaringType().getName()
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* A new query "Cleartext storage of sensitive information in the Android filesystem" (`java/android/cleartext-storage-filesystem`) has been added. This query finds instances of sensitive data being stored in local files without encryption, which may expose it to attackers or malicious applications.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Two new queries, "Android fragment injection" (`java/android/fragment-injection`) and "Android fragment injection in PreferenceActivity" (`java/android/fragment-injection-preference-activity`) have been added.
|
||||
These queries find exported Android activities that instantiate and host fragments created from user-provided data. Such activities are vulnerable to access control bypass and expose the Android application to unintended effects.
|
||||
1
java/ql/src/change-notes/released/0.0.6.md
Normal file
1
java/ql/src/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-queries
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.7-dev
|
||||
groups: java
|
||||
suites: codeql-suites
|
||||
extractor: java
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
| java.io.PrintStream#println(Object) | 3 |
|
||||
| java.lang.Class#isAssignableFrom(Class) | 1 |
|
||||
| java.lang.String#length() | 1 |
|
||||
| java.time.Duration#ofMillis(long) | 1 |
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.app"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="1"
|
||||
android:versionName="0.1" >
|
||||
|
||||
<application>
|
||||
<activity android:name=".CleartextStorageAndroidDatabaseTest"></activity>
|
||||
<activity android:name=".CleartextStorageAndroidFileSystemTest"></activity>
|
||||
<activity android:name=".CleartextStorageSharedPrefsTest"></activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,277 @@
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import androidx.security.crypto.EncryptedFile;
|
||||
import androidx.security.crypto.EncryptedFile.FileEncryptionScheme;
|
||||
|
||||
public class CleartextStorageAndroidFilesystemTest extends Activity {
|
||||
|
||||
public void testWriteLocalFile(Context context, String name, String password) throws Exception {
|
||||
|
||||
// FileOutputStream
|
||||
{
|
||||
// java.io;FileOutputStream;false;FileOutputStream;;;Argument[0];create-file
|
||||
FileOutputStream os = new FileOutputStream("some_file.txt");
|
||||
// Nested writers
|
||||
Writer writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
|
||||
// java.io;FileOutputStream;false;write;;;Argument[0];write-file
|
||||
writer.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
writer.close();
|
||||
}
|
||||
|
||||
// RandomAccessFile
|
||||
{
|
||||
// java.io;RandomAccessFile;false;RandomAccessFile;;;Argument[0];create-file
|
||||
RandomAccessFile f = new RandomAccessFile("some_file.txt", "r");
|
||||
String contents = name + ":" + password;
|
||||
// java.io;RandomAccessFile;false;write;;;Argument[0];write-file
|
||||
f.write(contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
|
||||
f.close();
|
||||
}
|
||||
{
|
||||
// try-with-resources
|
||||
try (RandomAccessFile f = new RandomAccessFile(new File("some_file.txt"), "r")) {
|
||||
// java.io;RandomAccessFile;false;writeBytes;;;Argument[0];write-file
|
||||
f.writeBytes(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
}
|
||||
}
|
||||
{
|
||||
RandomAccessFile f = new RandomAccessFile("some_file.txt", "r");
|
||||
// java.io;RandomAccessFile;false;writeChars;;;Argument[0];write-file
|
||||
f.writeChars(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
f.close();
|
||||
}
|
||||
{
|
||||
RandomAccessFile f = new RandomAccessFile("some_file.txt", "r");
|
||||
// java.io;RandomAccessFile;false;writeUTF;;;Argument[0];write-file
|
||||
f.writeUTF(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
f.close();
|
||||
}
|
||||
|
||||
// FileWriter
|
||||
{
|
||||
// java.io;FileWriter;false;FileWriter;;;Argument[0];create-file
|
||||
FileWriter fw = new FileWriter("some_file.txt");
|
||||
// java.io;Writer;true;append;;;Argument[0];write-file
|
||||
fw.append(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
fw.close();
|
||||
}
|
||||
{
|
||||
// try-with-resources
|
||||
try (FileWriter fw = new FileWriter("some_file.txt")) {
|
||||
// java.io;Writer;true;write;;;Argument[0];write-file
|
||||
fw.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
}
|
||||
}
|
||||
|
||||
// PrintStream
|
||||
{
|
||||
// java.io;PrintStream;false;PrintStream;(File);;Argument[0];create-file"
|
||||
PrintStream ps = new PrintStream(new File("some_file.txt"));
|
||||
// java.io;PrintStream;true;append;;;Argument[0];write-file
|
||||
ps.append(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintStream;false;PrintStream;(File,String);;Argument[0];create-file
|
||||
PrintStream ps = new PrintStream(new File("some_file.txt"), "utf-8");
|
||||
// java.io;PrintStream;true;format;(String,Object[]);;Argument[0..1];write-file
|
||||
ps.format("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.format("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintStream;false;PrintStream;(File,Charset);;Argument[0];create-file
|
||||
PrintStream ps = new PrintStream(new File("some_file.txt"), Charset.defaultCharset());
|
||||
// java.io;PrintStream;true;format;(Locale,String,Object[]);;Argument[1..2];write-file
|
||||
ps.format(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.format(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintStream;false;PrintStream;(String);;Argument[0];create-file
|
||||
PrintStream ps = new PrintStream("some_file.txt");
|
||||
// java.io;PrintStream;true;print;;;Argument[0];write-file
|
||||
ps.print(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintStream;false;PrintStream;(String,String);;Argument[0];create-file
|
||||
PrintStream ps = new PrintStream("some_file.txt", "utf-8");
|
||||
// java.io;PrintStream;true;printf;(String,Object[]);;Argument[0..1];write-file
|
||||
ps.printf("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.printf("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintStream;false;PrintStream;(String,Charset);;Argument[0];create-file
|
||||
PrintStream ps = new PrintStream("some_file.txt", Charset.defaultCharset());
|
||||
// java.io;PrintStream;true;printf;(Locale,String,Object[]);;Argument[1..2];write-file
|
||||
ps.printf(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.printf(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
PrintStream ps = new PrintStream("some_file.txt");
|
||||
// java.io;PrintStream;true;println;;;Argument[0];write-file
|
||||
ps.println(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
PrintStream ps = new PrintStream("some_file.txt");
|
||||
String contents = name + ":" + password;
|
||||
// java.io;PrintStream;true;write;;;Argument[0];write-file
|
||||
ps.write(contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
{
|
||||
PrintStream ps = new PrintStream("some_file.txt");
|
||||
String contents = name + ":" + password;
|
||||
// java.io;PrintStream;true;writeBytes;;;Argument[0];write-file
|
||||
ps.writeBytes(contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
|
||||
ps.close();
|
||||
}
|
||||
|
||||
// PrintWriter
|
||||
{
|
||||
// java.io;PrintWriter;false;PrintWriter;(File);;Argument[0];create-file
|
||||
PrintWriter pw = new PrintWriter(new File("some_file.txt"));
|
||||
// java.io;Writer;true;append;;;Argument[0];write-file
|
||||
pw.append(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
{
|
||||
// try-with-resources
|
||||
try (PrintWriter pw = new PrintWriter(new File("some_file.txt"))) {
|
||||
// java.io;PrintWriter;false;format;(String,Object[]);;Argument[0..1];write-file
|
||||
pw.format("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.format("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
}
|
||||
}
|
||||
{
|
||||
// java.io;PrintWriter;false;PrintWriter;(File,String);;Argument[0];create-file
|
||||
PrintWriter pw = new PrintWriter(new File("some_file.txt"), "utf-8");
|
||||
// java.io;PrintWriter;false;format;(Locale,String,Object[]);;Argument[1..2];write-file
|
||||
pw.format(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.format(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintWriter;false;PrintWriter;(File,Charset);;Argument[0];create-file
|
||||
PrintWriter pw = new PrintWriter(new File("some_file.txt"), Charset.defaultCharset());
|
||||
// java.io;PrintWriter;false;print;;;Argument[0];write-file
|
||||
pw.print(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
|
||||
{
|
||||
// java.io;PrintWriter;false;PrintWriter;(String);;Argument[0];create-file
|
||||
PrintWriter pw = new PrintWriter("some_file.txt");
|
||||
// java.io;PrintWriter;false;printf;(String,Object[]);;Argument[0..1];write-file
|
||||
pw.printf("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.printf("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintWriter;false;PrintWriter;(String,String);;Argument[0];create-file
|
||||
PrintWriter pw = new PrintWriter("some_file.txt", "utf-8");
|
||||
// java.io;PrintWriter;false;printf;(Locale,String,Object[]);;Argument[1..2];write-file
|
||||
pw.printf(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.printf(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
{
|
||||
// java.io;PrintWriter;false;PrintWriter;(String,Charset);;Argument[0];create-file
|
||||
PrintWriter pw = new PrintWriter("some_file.txt", Charset.defaultCharset());
|
||||
// java.io;PrintWriter;false;println;;;Argument[0];write-file
|
||||
pw.println(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
{
|
||||
PrintWriter pw = new PrintWriter("some_file.txt");
|
||||
// java.io;Writer;true;write;;;Argument[0];write-file
|
||||
pw.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
pw.close();
|
||||
}
|
||||
|
||||
// java.nio.files.Files
|
||||
{
|
||||
// java.nio.file;Files;false;newBufferedWriter;;;Argument[0];create-file
|
||||
BufferedWriter bw = Files.newBufferedWriter(Path.of("some_file.txt"));
|
||||
bw.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
bw.close();
|
||||
}
|
||||
{
|
||||
// java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file
|
||||
// try-with-resources
|
||||
try (OutputStream os = Files.newOutputStream(Path.of("some_file.txt"))) {
|
||||
String contents = name + ":" + password;
|
||||
os.write(contents.getBytes());
|
||||
}
|
||||
}
|
||||
{
|
||||
Path path = Path.of("some_file.txt");
|
||||
String contents = name + ":" + password;
|
||||
// java.nio.file;Files;false;write;;;Argument[0];create-file
|
||||
// java.nio.file;Files;false;write;;;Argument[1];write-file",
|
||||
Files.write(path, contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
|
||||
}
|
||||
{
|
||||
Path path = Path.of("some_file.txt");
|
||||
String contents = name + ":" + password;
|
||||
Files.write(path, List.of(contents)); // $ hasCleartextStorageAndroidFilesystem
|
||||
}
|
||||
{
|
||||
Path path = Path.of("some_file.txt");
|
||||
// java.nio.file;Files;false;writeString;;;Argument[0];create-file
|
||||
// java.nio.file;Files;false;writeString;;;Argument[1];write-file"
|
||||
Files.writeString(path, name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
|
||||
}
|
||||
|
||||
// Safe writes
|
||||
{
|
||||
FileWriter fw = new FileWriter("some_file.txt");
|
||||
fw.write(name + ":" + hash(password)); // Safe - using a hash
|
||||
fw.close();
|
||||
}
|
||||
{
|
||||
Writer writer = new OutputStreamWriter(new ByteArrayOutputStream(), "utf-8");
|
||||
writer.write(name + ":" + password); // Safe - not writing to a file
|
||||
writer.close();
|
||||
}
|
||||
{
|
||||
File file = new File("some_file.txt");
|
||||
String contents = name + ":" + password;
|
||||
EncryptedFile encryptedFile = new EncryptedFile.Builder(file, context, "some_key",
|
||||
FileEncryptionScheme.AES256_GCM_HKDF_4KB).build();
|
||||
FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();
|
||||
encryptedOutputStream.write(contents.getBytes()); // Safe - using EncryptedFile
|
||||
}
|
||||
}
|
||||
|
||||
private static String hash(String cleartext) throws Exception {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
|
||||
String encoded = Base64.getEncoder().encodeToString(hash);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import java
|
||||
import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class CleartextStorageAndroidFilesystemTest extends InlineExpectationsTest {
|
||||
CleartextStorageAndroidFilesystemTest() { this = "CleartextStorageAndroidFilesystemTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasCleartextStorageAndroidFilesystem" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasCleartextStorageAndroidFilesystem" and
|
||||
exists(SensitiveSource data, LocalFileOpenCall s, Expr input, Expr store |
|
||||
input = s.getAnInput() and
|
||||
store = s.getAStore() and
|
||||
data.flowsTo(input)
|
||||
|
|
||||
input.getLocation() = location and
|
||||
element = input.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
package="com.example.myapp">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".SafePreferenceActivity" android:exported="true" />
|
||||
<activity android:name=".UnsafePreferenceActivity" android:exported="true" />
|
||||
<activity android:name=".UnexportedPreferenceActivity" android:exported="false" />
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,18 @@
|
||||
import java
|
||||
import semmle.code.java.security.FragmentInjection
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class FragmentInjectionInPreferenceActivityTest extends InlineExpectationsTest {
|
||||
FragmentInjectionInPreferenceActivityTest() { this = "FragmentInjectionInPreferenceActivityTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasPreferenceFragmentInjection" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasPreferenceFragmentInjection" and
|
||||
exists(IsValidFragmentMethod isValidFragment | isValidFragment.isUnsafe() |
|
||||
isValidFragment.getLocation() = location and
|
||||
element = isValidFragment.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
import semmle.code.java.security.FragmentInjectionQuery
|
||||
import TestUtilities.InlineFlowTest
|
||||
|
||||
class Test extends InlineFlowTest {
|
||||
override DataFlow::Configuration getValueFlowConfig() { none() }
|
||||
|
||||
override TaintTracking::Configuration getTaintFlowConfig() {
|
||||
result instanceof FragmentInjectionTaintConf
|
||||
}
|
||||
}
|
||||
39
java/ql/test/query-tests/security/CWE-470/MainActivity.java
Normal file
39
java/ql/test/query-tests/security/CWE-470/MainActivity.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.example.myapp;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
public class MainActivity extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstance) {
|
||||
try {
|
||||
super.onCreate(savedInstance);
|
||||
final String fname = getIntent().getStringExtra("fname");
|
||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
Class<Fragment> fClass = (Class<Fragment>) Class.forName(fname);
|
||||
ft.add(fClass.newInstance(), ""); // $ hasTaintFlow
|
||||
ft.add(0, Fragment.instantiate(this, fname), null); // $ hasTaintFlow
|
||||
ft.add(0, Fragment.instantiate(this, fname, null)); // $ hasTaintFlow
|
||||
ft.add(0, fClass, null, ""); // $ hasTaintFlow
|
||||
ft.add(0, fClass.newInstance(), ""); // $ hasTaintFlow
|
||||
ft.attach(fClass.newInstance()); // $ hasTaintFlow
|
||||
ft.replace(0, fClass, null); // $ hasTaintFlow
|
||||
ft.replace(0, fClass.newInstance()); // $ hasTaintFlow
|
||||
ft.replace(0, fClass, null, ""); // $ hasTaintFlow
|
||||
ft.replace(0, fClass.newInstance(), ""); // $ hasTaintFlow
|
||||
|
||||
ft.add(Fragment.class.newInstance(), ""); // Safe
|
||||
ft.attach(Fragment.class.newInstance()); // Safe
|
||||
ft.replace(0, Fragment.class.newInstance(), ""); // Safe
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.myapp;
|
||||
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
public class SafePreferenceActivity extends PreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected boolean isValidFragment(String fragmentName) { // Safe: not all paths return true
|
||||
return fragmentName.equals("MySafeFragment") || fragmentName.equals("MySafeFragment2");
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user