mirror of
https://github.com/github/codeql.git
synced 2026-03-01 05:13:41 +01:00
Merge pull request #3349 from aschackmull/java/qldoc1
Java: Improve qldoc coverage.
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about instances of
|
||||
* `java.util.Collection` and their methods.
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
@@ -77,6 +82,7 @@ class CollectionMutator extends CollectionMethod {
|
||||
class CollectionMutation extends MethodAccess {
|
||||
CollectionMutation() { this.getMethod() instanceof CollectionMutator }
|
||||
|
||||
/** Holds if the result of this call is not immediately discarded. */
|
||||
predicate resultIsChecked() { not this.getParent() instanceof ExprStmt }
|
||||
}
|
||||
|
||||
|
||||
@@ -68,21 +68,27 @@ newtype Completion =
|
||||
*/
|
||||
ThrowCompletion(ThrowableType tt)
|
||||
|
||||
/** A completion that is either a `NormalCompletion` or a `BooleanCompletion`. */
|
||||
class NormalOrBooleanCompletion extends Completion {
|
||||
NormalOrBooleanCompletion() {
|
||||
this instanceof NormalCompletion or this instanceof BooleanCompletion
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this completion. */
|
||||
string toString() { result = "completion" }
|
||||
}
|
||||
|
||||
/** Gets the completion `ContinueCompletion(NoLabel())`. */
|
||||
ContinueCompletion anonymousContinueCompletion() { result = ContinueCompletion(NoLabel()) }
|
||||
|
||||
/** Gets the completion `ContinueCompletion(JustLabel(l))`. */
|
||||
ContinueCompletion labelledContinueCompletion(Label l) { result = ContinueCompletion(JustLabel(l)) }
|
||||
|
||||
/** Gets the completion `BreakCompletion(NoLabel())`. */
|
||||
BreakCompletion anonymousBreakCompletion() { result = BreakCompletion(NoLabel()) }
|
||||
|
||||
/** Gets the completion `BreakCompletion(JustLabel(l))`. */
|
||||
BreakCompletion labelledBreakCompletion(Label l) { result = BreakCompletion(JustLabel(l)) }
|
||||
|
||||
/** Gets the completion `booleanCompletion(value, value)`. */
|
||||
/** Gets the completion `BooleanCompletion(value, value)`. */
|
||||
Completion basicBooleanCompletion(boolean value) { result = BooleanCompletion(value, value) }
|
||||
|
||||
@@ -113,6 +113,7 @@ class ControlFlowNode extends Top, @exprparent {
|
||||
result = succ(this, NormalCompletion())
|
||||
}
|
||||
|
||||
/** Gets the basic block that contains this node. */
|
||||
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||
}
|
||||
|
||||
|
||||
@@ -844,6 +844,7 @@ class EqualityTest extends BinaryExpr {
|
||||
this instanceof NEExpr
|
||||
}
|
||||
|
||||
/** Gets a boolean indicating whether this is `==` (true) or `!=` (false). */
|
||||
boolean polarity() {
|
||||
result = true and this instanceof EQExpr
|
||||
or
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about instances of
|
||||
* `java.util.Map` and their methods.
|
||||
*/
|
||||
|
||||
import java
|
||||
import Collections
|
||||
|
||||
@@ -47,6 +52,7 @@ class MapSizeMethod extends MapMethod {
|
||||
class MapMutation extends MethodAccess {
|
||||
MapMutation() { this.getMethod() instanceof MapMutator }
|
||||
|
||||
/** Holds if the result of this call is not immediately discarded. */
|
||||
predicate resultIsChecked() { not this.getParent() instanceof ExprStmt }
|
||||
}
|
||||
|
||||
@@ -72,7 +78,9 @@ class FreshMap extends ClassInstanceExpr {
|
||||
class MapPutCall extends MethodAccess {
|
||||
MapPutCall() { getCallee().(MapMethod).hasName("put") }
|
||||
|
||||
/** Gets the key argument of this call. */
|
||||
Expr getKey() { result = getArgument(0) }
|
||||
|
||||
/** Gets the value argument of this call. */
|
||||
Expr getValue() { result = getArgument(1) }
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ import JDKAnnotations
|
||||
import Serializability
|
||||
import semmle.code.java.dataflow.DefUse
|
||||
|
||||
/** Holds if `f` is a field that may be read by reflection. */
|
||||
predicate reflectivelyRead(Field f) {
|
||||
f instanceof SerializableField or
|
||||
f.getAnAnnotation() instanceof ReflectiveAccessAnnotation or
|
||||
referencedInXmlFile(f)
|
||||
}
|
||||
|
||||
/** Holds if `f` is a field that may be written by reflection. */
|
||||
predicate reflectivelyWritten(Field f) {
|
||||
f instanceof DeserializableField or
|
||||
f.getAnAnnotation() instanceof ReflectiveAccessAnnotation or
|
||||
@@ -360,6 +362,7 @@ class ReflectiveFieldAccess extends ClassMethodAccess {
|
||||
this.getCallee().hasName("getDeclaredField")
|
||||
}
|
||||
|
||||
/** Gets the field accessed by this call. */
|
||||
Field inferAccessedField() {
|
||||
(
|
||||
if this.getCallee().hasName("getDeclaredField")
|
||||
|
||||
@@ -80,6 +80,7 @@ private newtype TFmtSyntax =
|
||||
|
||||
/** A syntax for format strings. */
|
||||
class FmtSyntax extends TFmtSyntax {
|
||||
/** Gets a textual representation of this format string syntax. */
|
||||
string toString() {
|
||||
result = "printf (%) syntax" and this = TFmtPrintf()
|
||||
or
|
||||
@@ -130,6 +131,7 @@ class FormattingCall extends Call {
|
||||
formatWrapper(this.getCallee(), result, _)
|
||||
}
|
||||
|
||||
/** Gets the format string syntax used by this call. */
|
||||
FmtSyntax getSyntax() {
|
||||
this.getCallee() instanceof StringFormatMethod and result = TFmtPrintf()
|
||||
or
|
||||
@@ -146,6 +148,7 @@ class FormattingCall extends Call {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this uses the "logger ({})" format syntax and the last argument is a `Throwable`. */
|
||||
predicate hasTrailingThrowableArgument() {
|
||||
getSyntax() = TFmtLogger() and
|
||||
getLastArg().getType().(RefType).getASourceSupertype*() instanceof TypeThrowable
|
||||
|
||||
@@ -637,10 +637,12 @@ class IntersectionType extends RefType, @class {
|
||||
|
||||
private RefType superInterface() { implInterface(this, result) }
|
||||
|
||||
/** Gets a textual representation of this type that includes all the intersected types. */
|
||||
string getLongName() {
|
||||
result = superType().toString() + concat(" & " + superInterface().toString())
|
||||
}
|
||||
|
||||
/** Gets the first bound of this intersection type. */
|
||||
RefType getFirstBound() { extendsReftype(this, result) }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about guards and the control
|
||||
* flow elements controlled by those guards.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import semmle.code.java.controlflow.Dominance
|
||||
private import semmle.code.java.controlflow.internal.GuardsLogic
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for representing abstract bounds for use in, for example, range analysis.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import SSA
|
||||
private import RangeUtils
|
||||
@@ -14,6 +18,7 @@ private newtype TBound =
|
||||
* A bound that may be inferred for an expression plus/minus an integer delta.
|
||||
*/
|
||||
abstract class Bound extends TBound {
|
||||
/** Gets a textual representation of this bound. */
|
||||
abstract string toString();
|
||||
|
||||
/** Gets an expression that equals this bound plus `delta`. */
|
||||
@@ -22,6 +27,13 @@ abstract class Bound extends TBound {
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getExpr() { result = getExpr(0) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `sc` of line `sl` to
|
||||
* column `ec` of line `el` in file `path`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
|
||||
}
|
||||
|
||||
@@ -152,9 +152,13 @@ deprecated class RemoteUserInput extends UserInput {
|
||||
RemoteUserInput() { this instanceof RemoteFlowSource }
|
||||
}
|
||||
|
||||
/** Input that may be controlled by a local user. */
|
||||
/** A node with input that may be controlled by a local user. */
|
||||
abstract class LocalUserInput extends UserInput { }
|
||||
|
||||
/**
|
||||
* A node with input from the local environment, such as files, standard in,
|
||||
* environment variables, and main method parameters.
|
||||
*/
|
||||
class EnvInput extends LocalUserInput {
|
||||
EnvInput() {
|
||||
// Parameters to a main method.
|
||||
@@ -180,6 +184,7 @@ class EnvInput extends LocalUserInput {
|
||||
}
|
||||
}
|
||||
|
||||
/** A node with input from a database. */
|
||||
class DatabaseInput extends LocalUserInput {
|
||||
DatabaseInput() { this.asExpr().(MethodAccess).getMethod() instanceof ResultSetGetStringMethod }
|
||||
}
|
||||
@@ -222,10 +227,12 @@ private class EnvTaintedMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
/** The type `java.net.InetAddress`. */
|
||||
class TypeInetAddr extends RefType {
|
||||
TypeInetAddr() { this.getQualifiedName() = "java.net.InetAddress" }
|
||||
}
|
||||
|
||||
/** A reverse DNS method. */
|
||||
class ReverseDNSMethod extends Method {
|
||||
ReverseDNSMethod() {
|
||||
this.getDeclaringType() instanceof TypeInetAddr and
|
||||
|
||||
@@ -579,7 +579,7 @@ private predicate varMaybeNullInBlock_corrCond(
|
||||
* - int: A means a specific integer value and B means any other value.
|
||||
*/
|
||||
|
||||
newtype TrackVarKind =
|
||||
private newtype TrackVarKind =
|
||||
TrackVarKindNull() or
|
||||
TrackVarKindBool() or
|
||||
TrackVarKindEnum() or
|
||||
@@ -701,7 +701,7 @@ private predicate isReset(
|
||||
}
|
||||
|
||||
/** The abstract value of the tracked variable. */
|
||||
newtype TrackedValue =
|
||||
private newtype TrackedValue =
|
||||
TrackedValueA() or
|
||||
TrackedValueB() or
|
||||
TrackedValueUnknown()
|
||||
|
||||
@@ -264,14 +264,21 @@ private newtype TReason =
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
abstract class Reason extends TReason {
|
||||
/** Gets a textual representation of this reason. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound that indicates that the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
class NoReason extends Reason, TNoReason {
|
||||
override string toString() { result = "NoReason" }
|
||||
}
|
||||
|
||||
/** A reason for an inferred bound pointing to a condition. */
|
||||
class CondReason extends Reason, TCondReason {
|
||||
/** Gets the condition that is the reason for the bound. */
|
||||
Guard getCond() { this = TCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
|
||||
@@ -142,6 +142,7 @@ class SsaReadPosition extends TSsaReadPosition {
|
||||
/** Holds if `v` is read at this position. */
|
||||
abstract predicate hasReadOfVar(SsaVariable v);
|
||||
|
||||
/** Gets a textual representation of this SSA read position. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ class SsaSourceVariable extends TSsaSourceVariable {
|
||||
this = TQualifiedField(result, _, _)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this `SsaSourceVariable`. */
|
||||
string toString() {
|
||||
exists(LocalScopeVariable v, Callable c | this = TLocalVar(c, v) |
|
||||
if c = v.getCallable()
|
||||
@@ -112,6 +113,7 @@ class SsaSourceVariable extends TSsaSourceVariable {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() {
|
||||
exists(LocalScopeVariable v | this = TLocalVar(_, v) and result = v.getLocation())
|
||||
or
|
||||
@@ -935,8 +937,10 @@ class SsaVariable extends TSsaVariable {
|
||||
this = TSsaUntracked(_, result)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this SSA variable. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { result = getCFGNode().getLocation() }
|
||||
|
||||
/** Gets the `BasicBlock` in which this SSA variable is defined. */
|
||||
@@ -1113,7 +1117,7 @@ class SsaPhiNode extends SsaVariable, TSsaPhiNode {
|
||||
}
|
||||
}
|
||||
|
||||
library class RefTypeCastExpr extends CastExpr {
|
||||
private class RefTypeCastExpr extends CastExpr {
|
||||
RefTypeCastExpr() { this.getType() instanceof RefType }
|
||||
}
|
||||
|
||||
|
||||
@@ -365,12 +365,12 @@ private predicate typeFlow(TypeFlowNode n, RefType t) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate erasedTypeBound(RefType t) {
|
||||
private predicate erasedTypeBound(RefType t) {
|
||||
exists(RefType t0 | typeFlow(_, t0) and t = t0.getErasure())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate typeBound(RefType t) { typeFlow(_, t) }
|
||||
private predicate typeBound(RefType t) { typeFlow(_, t) }
|
||||
|
||||
/**
|
||||
* Holds if we have a bound for `n` that is better than `t`, taking only erased
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* INTERNAL: This is part of the virtual dispatch computation.
|
||||
*
|
||||
* Provides a strengthening of the virtual dispatch relation using a dedicated
|
||||
* data flow check for lambdas, anonymous classes, and other sufficiently
|
||||
* private classes where all object instantiations are accounted for.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import VirtualDispatch
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides predicates for reasoning about runtime call targets through virtual
|
||||
* dispatch.
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.TypeFlow
|
||||
private import DispatchFlow as DispatchFlow
|
||||
@@ -27,6 +32,7 @@ Callable exactCallable(Call c) {
|
||||
|
||||
private predicate implCount(MethodAccess m, int c) { strictcount(viableImpl(m)) = c }
|
||||
|
||||
/** Gets a viable implementation of the target of the given `Call`. */
|
||||
Callable viableCallable(Call c) {
|
||||
result = viableImpl(c)
|
||||
or
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about calls that may invoke one
|
||||
* of their arguments.
|
||||
*/
|
||||
|
||||
import java
|
||||
import VirtualDispatch
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import java
|
||||
|
||||
newtype AssertKind =
|
||||
private newtype AssertKind =
|
||||
AssertKindTrue() or
|
||||
AssertKindFalse() or
|
||||
AssertKindNotNull() or
|
||||
@@ -50,6 +50,7 @@ private predicate assertionMethod(Method m, AssertKind kind) {
|
||||
)
|
||||
}
|
||||
|
||||
/** An assertion method. */
|
||||
class AssertionMethod extends Method {
|
||||
AssertionMethod() { assertionMethod(this, _) }
|
||||
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
/*
|
||||
/**
|
||||
* Definitions related to `java.net.*`.
|
||||
*/
|
||||
|
||||
import semmle.code.java.Type
|
||||
|
||||
/** The type `java.net.URLConnection`. */
|
||||
class TypeUrlConnection extends RefType {
|
||||
TypeUrlConnection() { hasQualifiedName("java.net", "URLConnection") }
|
||||
}
|
||||
|
||||
/** The type `java.net.Socket`. */
|
||||
class TypeSocket extends RefType {
|
||||
TypeSocket() { hasQualifiedName("java.net", "Socket") }
|
||||
}
|
||||
|
||||
/** The type `java.net.URL`. */
|
||||
class TypeUrl extends RefType {
|
||||
TypeUrl() { hasQualifiedName("java.net", "URL") }
|
||||
}
|
||||
|
||||
/** The method `java.net.URLConnection::getInputStream`. */
|
||||
class URLConnectionGetInputStreamMethod extends Method {
|
||||
URLConnectionGetInputStreamMethod() {
|
||||
getDeclaringType() instanceof TypeUrlConnection and
|
||||
@@ -24,6 +28,7 @@ class URLConnectionGetInputStreamMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
/** The method `java.net.Socket::getInputStream`. */
|
||||
class SocketGetInputStreamMethod extends Method {
|
||||
SocketGetInputStreamMethod() {
|
||||
getDeclaringType() instanceof TypeSocket and
|
||||
|
||||
Reference in New Issue
Block a user