Merge branch 'main' into atorralba/android-implicit-pending-intents

This commit is contained in:
Tony Torralba
2022-01-18 10:50:49 +01:00
committed by GitHub
160 changed files with 57757 additions and 48141 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +1,5 @@
## 0.0.6
## 0.0.5
## 0.0.4

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
more accurate length for integers formatted with `%x`

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -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

View File

@@ -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
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"
)
) and
reason = TTypeBoundsAnalysis()
or
this.getConversionChar(n).toLowerCase() = "p" and
exists(PointerType ptrType, int baseLen |

View File

@@ -1,3 +1,5 @@
## 0.0.6
## 0.0.5
### New Queries

View File

@@ -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,6 +38,8 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
* `sub.getLeftOperand()`.
*/
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
interestingSubExpr(sub, _) and // Manual magic
(
n.asExpr() = sub.getLeftOperand()
or
exists(DataFlow::Node other |
@@ -68,15 +72,22 @@ predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
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."

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.0.6-dev
version: 0.0.7-dev
groups: cpp
dependencies:
codeql/cpp-all: "*"

View File

@@ -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. |

View File

@@ -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

View File

@@ -0,0 +1,3 @@
description: Remove 'using_global' relation.
compatibility: backwards
using_global.rel: delete

View File

@@ -0,0 +1,5 @@
name: codeql/csharp-downgrades
groups: csharp
version: 0.0.6-dev
downgrades: .
library: true

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -0,0 +1 @@
## 0.0.7

View File

@@ -0,0 +1,6 @@
import csharp
query predicate missingPrimaryQlClass(Element e) {
not exists(e.getAPrimaryQlClass()) and
e.fromSource()
}

View File

@@ -1,3 +1,5 @@
## 0.0.6
## 0.0.5
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -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

View File

@@ -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" }
}
/**

View File

@@ -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" }
}

View File

@@ -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.
*

View File

@@ -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" }
}
/**

View File

@@ -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) }
}
/**

View File

@@ -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" }
}
/**

View File

@@ -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) {

View File

@@ -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"`. */

View File

@@ -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" }
}
/**

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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" }
}

View File

@@ -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

View File

@@ -0,0 +1,2 @@
description: Add 'using_global' relation.
compatibility: backwards

View File

@@ -1,3 +1,5 @@
## 0.0.6
## 0.0.5
## 0.0.4

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -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

View File

@@ -0,0 +1,3 @@
global using System;
global using System.IO;
global using static System.Text.Encoding;

View File

@@ -0,0 +1,9 @@
using System.Collections;
public class MyClass1
{
public void HelloWorld()
{
Console.WriteLine("Hello World");
}
}

View File

@@ -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 |

View 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
View 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.

View File

@@ -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
1 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
2 android.app 7 84 7 13 71
3 android.content 24 27 96 16 8 27 31 65
4 android.database 59 30 59 30
5 android.net 60 45 15
6 android.os 122 41 81
7 android.util 6 16 6 16
8 android.webkit 3 2 3 2
9 androidx.slice 5 88 5 27 61
10 cn.hutool.core.codec 1 1
11 com.esotericsoftware.kryo.io 1 1
12 com.esotericsoftware.kryo5.io 1 1
13 com.fasterxml.jackson.core 1 1
14 com.fasterxml.jackson.databind 6 6
15 com.google.common.base 85 62 23
16 com.google.common.cache 17 17
17 com.google.common.collect 553 2 551
18 com.google.common.flogger 29 29
19 com.google.common.io 6 73 6 72 1
20 com.opensymphony.xwork2.ognl 3 3
21 com.unboundid.ldap.sdk 17 17
22 flexjson 1 1
23 groovy.lang 26 26
24 groovy.util 5 5
25 jakarta.faces.context 2 7 2 7
26 jakarta.json 123 100 23
27 jakarta.ws.rs.client 1 1
28 jakarta.ws.rs.container 9 9
29 jakarta.ws.rs.core 2 149 2 94 55
30 java.beans 1 1
31 java.io 3 37 31 3 15 22 30 1
32 java.lang 8 56 8 45 11
33 java.net 10 3 7 10 3 7
34 java.nio 10 15 4 10 13 2 4
35 java.sql 7 7
36 java.util 34 430 34 16 414
37 javax.faces.context 2 7 2 7
38 javax.json 123 100 23
39 javax.management.remote 2 2
40 javax.naming 7 6 1
41 javax.net.ssl 2 2
42 javax.script 1 1
43 javax.servlet 4 21 2 3 1 21 2
44 javax.validation 1 1 1 1
45 javax.ws.rs.client 1 1
46 javax.ws.rs.container 9 9
47 javax.ws.rs.core 3 149 1 2 94 55
48 javax.xml.transform 1 6 1 6
49 javax.xml.xpath 3 3
50 jodd.json 10 10
51 net.sf.saxon.s9api 5 5
52 ognl 6 6
53 org.apache.commons.codec 6 6
54 org.apache.commons.collections 800 17 783
55 org.apache.commons.collections4 800 17 783
56 org.apache.commons.io 22 22
57 org.apache.commons.jexl2 15 15
58 org.apache.commons.jexl3 15 15
59 org.apache.commons.lang3 424 293 131
60 org.apache.commons.logging 6 6
61 org.apache.commons.ognl 6 6
62 org.apache.commons.text 272 220 52
63 org.apache.directory.ldap.client.api 1 1
64 org.apache.hc.core5.function 1 1
65 org.apache.hc.core5.http 1 2 39 1 2 39
66 org.apache.hc.core5.net 2 2
67 org.apache.hc.core5.util 24 18 6
68 org.apache.http 27 3 70 25 2 3 62 8
69 org.apache.ibatis.jdbc 6 6
70 org.apache.log4j 11 11
71 org.apache.logging.log4j 359 8 359 4 4
72 org.apache.shiro.codec 1 1
73 org.apache.shiro.jndi 1 1
74 org.codehaus.groovy.control 1 1
75 org.dom4j 20 20
76 org.hibernate 7 7
77 org.jboss.logging 324 324
78 org.jooq 1 1
79 org.json 236 198 38
80 org.mvel2 16 16
81 org.scijava.log 13 13
82 org.slf4j 55 6 55 2 4
83 org.springframework.beans 26 26
84 org.springframework.cache 13 13
85 org.springframework.context 3 3
86 org.springframework.http 14 70 14 60 10
87 org.springframework.jdbc.core 10 10
88 org.springframework.jdbc.object 9 9
89 org.springframework.jndi 1 1
90 org.springframework.ldap 42 28 14
91 org.springframework.security.web.savedrequest 6 6
92 org.springframework.ui 32 32
93 org.springframework.util 139 87 52
94 org.springframework.validation 13 13
95 org.springframework.web.client 13 3 13 3
96 org.springframework.web.context.request 8 8
97 org.springframework.web.multipart 12 13 12 13
98 org.springframework.web.reactive.function.client 2 2
99 org.springframework.web.util 163 138 25
100 org.xml.sax 1 1
101 org.xmlpull.v1 3 3
102 play.mvc 4 4
103 ratpack.core.form 3 3
104 ratpack.core.handling 6 4 6 4
105 ratpack.core.http 10 10 10 10
106 ratpack.exec 48 48
107 ratpack.form 3 3
108 ratpack.func 35 35
109 ratpack.handling 6 4 6 4
110 ratpack.http 10 10 10 10
111 ratpack.util 35 35

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;
/**

View 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")
}
}

View File

@@ -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
)
}
}

View 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"
]
}
}

View 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()
)
}
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -1,3 +1,5 @@
## 0.0.6
## 0.0.5
### Minor Analysis Improvements

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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"

View 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>

View 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) {
}
}
}

View File

@@ -0,0 +1,4 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<include src="FragmentInjection.inc.qhelp"></include>
</qhelp>

View 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"

View File

@@ -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);
}
}

View File

@@ -0,0 +1,4 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<include src="FragmentInjection.inc.qhelp"></include>
</qhelp>

View File

@@ -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()

View File

@@ -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.

View File

@@ -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.

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -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

View File

@@ -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 |

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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 = ""
)
}
}

View File

@@ -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>

View File

@@ -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 = ""
)
}
}

View File

@@ -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
}
}

View 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) {
}
}
}

View File

@@ -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