mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge remote-tracking branch 'upstream/main' into main
This commit is contained in:
@@ -653,11 +653,23 @@ class LongLiteral extends Literal, @longliteral {
|
||||
|
||||
/** A floating point literal. For example, `4.2f`. */
|
||||
class FloatingPointLiteral extends Literal, @floatingpointliteral {
|
||||
/**
|
||||
* Gets the value of this literal as CodeQL 64-bit `float`. The value will
|
||||
* be parsed as Java 32-bit `float` and then converted to a CodeQL `float`.
|
||||
*/
|
||||
float getFloatValue() { result = getValue().toFloat() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FloatingPointLiteral" }
|
||||
}
|
||||
|
||||
/** A double literal. For example, `4.2`. */
|
||||
class DoubleLiteral extends Literal, @doubleliteral {
|
||||
/**
|
||||
* Gets the value of this literal as CodeQL 64-bit `float`. The result will
|
||||
* have the same effective value as the Java `double` literal.
|
||||
*/
|
||||
float getDoubleValue() { result = getValue().toFloat() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DoubleLiteral" }
|
||||
}
|
||||
|
||||
|
||||
@@ -26,15 +26,243 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
|
||||
tupleLimit = 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
|
||||
* currently excludes read-steps, store-steps, and flow-through.
|
||||
*
|
||||
* The analysis uses non-linear recursion: When computing a flow path in or out
|
||||
* of a call, we use the results of the analysis recursively to resolve lamba
|
||||
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||
*/
|
||||
private module LambdaFlow {
|
||||
private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
|
||||
p.isParameterOf(viableCallable(call), i)
|
||||
}
|
||||
|
||||
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), i)
|
||||
}
|
||||
|
||||
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
||||
exists(int i |
|
||||
viableParamNonLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
||||
exists(int i |
|
||||
viableParamLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TReturnPositionSimple =
|
||||
TReturnPositionSimple0(DataFlowCallable c, ReturnKind kind) {
|
||||
exists(ReturnNode ret |
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private TReturnPositionSimple getReturnPositionSimple(ReturnNode ret, ReturnKind kind) {
|
||||
result = TReturnPositionSimple0(getNodeEnclosingCallable(ret), kind)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TReturnPositionSimple viableReturnPosNonLambda(DataFlowCall call, ReturnKind kind) {
|
||||
result = TReturnPositionSimple0(viableCallable(call), kind)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TReturnPositionSimple viableReturnPosLambda(
|
||||
DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind
|
||||
) {
|
||||
result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind)
|
||||
}
|
||||
|
||||
private predicate viableReturnPosOutNonLambda(
|
||||
DataFlowCall call, TReturnPositionSimple pos, OutNode out
|
||||
) {
|
||||
exists(ReturnKind kind |
|
||||
pos = viableReturnPosNonLambda(call, kind) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate viableReturnPosOutLambda(
|
||||
DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out
|
||||
) {
|
||||
exists(ReturnKind kind |
|
||||
pos = viableReturnPosLambda(call, lastCall, kind) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `node` (of type `t`) to
|
||||
* the lambda call `lambdaCall`.
|
||||
*
|
||||
* The parameter `toReturn` indicates whether the path from `node` to
|
||||
* `lambdaCall` goes through a return, and `toJump` whether the path goes
|
||||
* through a jump step.
|
||||
*
|
||||
* The call context `lastCall` records the last call on the path from `node`
|
||||
* to `lambdaCall`, if any. That is, `lastCall` is able to target the enclosing
|
||||
* callable of `lambdaCall`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlow(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
|
||||
boolean toJump, DataFlowCallOption lastCall
|
||||
) {
|
||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
||||
then compatibleTypes(t, getNodeType(node))
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlow0(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
|
||||
boolean toJump, DataFlowCallOption lastCall
|
||||
) {
|
||||
lambdaCall(lambdaCall, kind, node) and
|
||||
t = getNodeType(node) and
|
||||
toReturn = false and
|
||||
toJump = false and
|
||||
lastCall = TDataFlowCallNone()
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid, DataFlowType t0 |
|
||||
revLambdaFlow(lambdaCall, kind, mid, t0, toReturn, toJump, lastCall)
|
||||
|
|
||||
simpleLocalFlowStep(node, mid) and
|
||||
t = t0
|
||||
or
|
||||
exists(boolean preservesValue |
|
||||
additionalLambdaFlowStep(node, mid, preservesValue) and
|
||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||
|
|
||||
preservesValue = false and
|
||||
t = getNodeType(node)
|
||||
or
|
||||
preservesValue = true and
|
||||
t = t0
|
||||
)
|
||||
)
|
||||
or
|
||||
// jump step
|
||||
exists(Node mid, DataFlowType t0 |
|
||||
revLambdaFlow(lambdaCall, kind, mid, t0, _, _, _) and
|
||||
toReturn = false and
|
||||
toJump = true and
|
||||
lastCall = TDataFlowCallNone()
|
||||
|
|
||||
jumpStep(node, mid) and
|
||||
t = t0
|
||||
or
|
||||
exists(boolean preservesValue |
|
||||
additionalLambdaFlowStep(node, mid, preservesValue) and
|
||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||
|
|
||||
preservesValue = false and
|
||||
t = getNodeType(node)
|
||||
or
|
||||
preservesValue = true and
|
||||
t = t0
|
||||
)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
|
||||
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||
(
|
||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||
then lastCall = TDataFlowCallSome(call)
|
||||
else lastCall = lastCall0
|
||||
) and
|
||||
toReturn = false
|
||||
|
|
||||
viableParamArgNonLambda(call, p, node)
|
||||
or
|
||||
viableParamArgLambda(call, p, node) // non-linear recursion
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(TReturnPositionSimple pos |
|
||||
revLambdaFlowOut(lambdaCall, kind, pos, t, toJump, lastCall) and
|
||||
getReturnPositionSimple(node, node.(ReturnNode).getKind()) = pos and
|
||||
toReturn = true
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlowOutLambdaCall(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, OutNode out, DataFlowType t, boolean toJump,
|
||||
DataFlowCall call, DataFlowCallOption lastCall
|
||||
) {
|
||||
revLambdaFlow(lambdaCall, kind, out, t, _, toJump, lastCall) and
|
||||
exists(ReturnKindExt rk |
|
||||
out = rk.getAnOutNode(call) and
|
||||
lambdaCall(call, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlowOut(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,
|
||||
boolean toJump, DataFlowCallOption lastCall
|
||||
) {
|
||||
exists(DataFlowCall call, OutNode out |
|
||||
revLambdaFlow(lambdaCall, kind, out, t, _, toJump, lastCall) and
|
||||
viableReturnPosOutNonLambda(call, pos, out)
|
||||
or
|
||||
// non-linear recursion
|
||||
revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and
|
||||
viableReturnPosOutLambda(call, _, pos, out)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlowIn(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
||||
DataFlowCallOption lastCall
|
||||
) {
|
||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||
}
|
||||
}
|
||||
|
||||
private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
||||
result = viableCallable(call)
|
||||
or
|
||||
result = viableCallableLambda(call, _)
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* Gets a viable target for the lambda call `call`.
|
||||
*
|
||||
* `lastCall` records the call required to reach `call` in order for the result
|
||||
* to be a viable target, if any.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable viableCallableLambda(DataFlowCall call, DataFlowCallOption lastCall) {
|
||||
exists(Node creation, LambdaCallKind kind |
|
||||
LambdaFlow::revLambdaFlow(call, kind, creation, _, _, _, lastCall) and
|
||||
lambdaCreation(creation, kind, result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
|
||||
* The instance parameter is considered to have index `-1`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
|
||||
p.isParameterOf(viableCallable(call), i)
|
||||
p.isParameterOf(viableCallableExt(call), i)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +280,7 @@ private module Cached {
|
||||
|
||||
pragma[nomagic]
|
||||
private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) {
|
||||
viableCallable(call) = result.getCallable() and
|
||||
viableCallableExt(call) = result.getCallable() and
|
||||
kind = result.getKind()
|
||||
}
|
||||
|
||||
@@ -317,6 +545,35 @@ private module Cached {
|
||||
|
||||
cached
|
||||
private module DispatchWithCallContext {
|
||||
/**
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||
mayBenefitFromCallContext(call, callable)
|
||||
or
|
||||
callable = call.getEnclosingCallable() and
|
||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx)
|
||||
or
|
||||
result = viableCallableLambda(call, TDataFlowCallSome(ctx))
|
||||
or
|
||||
exists(DataFlowCallable enclosing |
|
||||
mayBenefitFromCallContextExt(call, enclosing) and
|
||||
enclosing = viableCallableExt(ctx) and
|
||||
result = viableCallableLambda(call, TDataFlowCallNone())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `ctx` reduces the set of viable run-time
|
||||
* dispatch targets of call `call` in `c`.
|
||||
@@ -324,10 +581,10 @@ private module Cached {
|
||||
cached
|
||||
predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c, DataFlowCall ctx) {
|
||||
exists(int tgts, int ctxtgts |
|
||||
mayBenefitFromCallContext(call, c) and
|
||||
c = viableCallable(ctx) and
|
||||
ctxtgts = count(viableImplInCallContext(call, ctx)) and
|
||||
tgts = strictcount(viableCallable(call)) and
|
||||
mayBenefitFromCallContextExt(call, c) and
|
||||
c = viableCallableExt(ctx) and
|
||||
ctxtgts = count(viableImplInCallContextExt(call, ctx)) and
|
||||
tgts = strictcount(viableCallableExt(call)) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
@@ -339,7 +596,7 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx) and
|
||||
result = viableImplInCallContextExt(call, ctx) and
|
||||
reducedViableImplInCallContext(call, _, ctx)
|
||||
}
|
||||
|
||||
@@ -351,10 +608,10 @@ private module Cached {
|
||||
cached
|
||||
predicate reducedViableImplInReturn(DataFlowCallable c, DataFlowCall call) {
|
||||
exists(int tgts, int ctxtgts |
|
||||
mayBenefitFromCallContext(call, _) and
|
||||
c = viableCallable(call) and
|
||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContext(call, ctx)) and
|
||||
tgts = strictcount(DataFlowCall ctx | viableCallable(ctx) = call.getEnclosingCallable()) and
|
||||
mayBenefitFromCallContextExt(call, _) and
|
||||
c = viableCallableExt(call) and
|
||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
|
||||
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
@@ -367,7 +624,7 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContext(call, ctx) and
|
||||
result = viableImplInCallContextExt(call, ctx) and
|
||||
reducedViableImplInReturn(result, call)
|
||||
}
|
||||
}
|
||||
@@ -481,6 +738,11 @@ private module Cached {
|
||||
TBooleanNone() or
|
||||
TBooleanSome(boolean b) { b = true or b = false }
|
||||
|
||||
cached
|
||||
newtype TDataFlowCallOption =
|
||||
TDataFlowCallNone() or
|
||||
TDataFlowCallSome(DataFlowCall call)
|
||||
|
||||
cached
|
||||
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
|
||||
|
||||
@@ -777,7 +1039,7 @@ ReturnPosition getReturnPosition(ReturnNodeExt ret) {
|
||||
|
||||
bindingset[cc, callable]
|
||||
predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) {
|
||||
cc instanceof CallContextAny and callable = viableCallable(call)
|
||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||
or
|
||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||
call0.getEnclosingCallable() = callable and
|
||||
@@ -791,14 +1053,14 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
||||
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
|
||||
if reducedViableImplInCallContext(call, _, ctx)
|
||||
then result = prunedViableImplInCallContext(call, ctx)
|
||||
else result = viableCallable(call)
|
||||
else result = viableCallableExt(call)
|
||||
)
|
||||
or
|
||||
result = viableCallable(call) and cc instanceof CallContextSomeCall
|
||||
result = viableCallableExt(call) and cc instanceof CallContextSomeCall
|
||||
or
|
||||
result = viableCallable(call) and cc instanceof CallContextAny
|
||||
result = viableCallableExt(call) and cc instanceof CallContextAny
|
||||
or
|
||||
result = viableCallable(call) and cc instanceof CallContextReturn
|
||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||
}
|
||||
|
||||
predicate read = readStep/3;
|
||||
@@ -812,6 +1074,19 @@ class BooleanOption extends TBooleanOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** An optional `DataFlowCall`. */
|
||||
class DataFlowCallOption extends TDataFlowCallOption {
|
||||
string toString() {
|
||||
this = TDataFlowCallNone() and
|
||||
result = "(none)"
|
||||
or
|
||||
exists(DataFlowCall call |
|
||||
this = TDataFlowCallSome(call) and
|
||||
result = call.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Content tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
|
||||
@@ -338,3 +338,14 @@ predicate isImmutableOrUnobservable(Node n) {
|
||||
|
||||
/** Holds if `n` should be hidden from path explanations. */
|
||||
predicate nodeIsHidden(Node n) { none() }
|
||||
|
||||
class LambdaCallKind = Unit;
|
||||
|
||||
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() }
|
||||
|
||||
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() }
|
||||
|
||||
/** Extra data-flow steps needed for lamba flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
40
java/ql/src/semmle/code/java/frameworks/guava/Base.qll
Normal file
40
java/ql/src/semmle/code/java/frameworks/guava/Base.qll
Normal file
@@ -0,0 +1,40 @@
|
||||
/** Definitions of flow steps through utility methods of `com.google.common.base`. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
private class GuavaBaseCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
|
||||
"com.google.common.base;Strings;false;emptyToNull;(String);;Argument[0];ReturnValue;value",
|
||||
"com.google.common.base;Strings;false;nullToEmpty;(String);;Argument[0];ReturnValue;value",
|
||||
"com.google.common.base;Strings;false;padStart;(String,int,char);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Strings;false;padEnd;(String,int,char);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Strings;false;repeat;(String,int);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Strings;false;lenientFormat;(String,Object[]);;Argument;ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;on;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;skipNulls;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;useForNull;(String);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;useForNull;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;withKeyValueSeparator;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;withKeyValueSeparator;(String);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner;false;withKeyValueSeparator;(char);;Argument[-1];ReturnValue;taint",
|
||||
// Note: The signatures of some of the appendTo methods involve collection flow
|
||||
"com.google.common.base;Joiner;false;appendTo;;;Argument;Argument[0];taint",
|
||||
"com.google.common.base;Joiner;false;appendTo;;;Argument[0];ReturnValue;value",
|
||||
"com.google.common.base;Joiner;false;join;;;Argument;ReturnValue;taint",
|
||||
"com.google.common.base;Joiner$MapJoiner;false;useForNull;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner$MapJoiner;false;useForNull;(String);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.base;Joiner$MapJoiner;false;appendTo;;;Argument;Argument[0];taint",
|
||||
"com.google.common.base;Joiner$MapJoiner;false;appendTo;;;Argument[0];ReturnValue;value",
|
||||
"com.google.common.base;Joiner$MapJoiner;false;join;;;Argument;ReturnValue;taint",
|
||||
"com.google.common.base;Splitter;false;split;(CharSequence);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Splitter;false;splitToList;(CharSequence);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Splitter;false;splitToStream;(CharSequence);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Splitter$MapSplitter;false;split;(CharSequence);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.base;Preconditions;false;checkNotNull;;;Argument[0];ReturnValue;value"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import StringUtils
|
||||
import Base
|
||||
import Collections
|
||||
import Preconditions
|
||||
import IO
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/** Definitions of flow steps through the Preconditions class in the Guava framework. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
|
||||
/**
|
||||
* The class `com.google.common.base.Preconditions`.
|
||||
*/
|
||||
class TypeGuavaPreconditions extends Class {
|
||||
TypeGuavaPreconditions() { this.hasQualifiedName("com.google.common.base", "Preconditions") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that returns its argumnets.
|
||||
*/
|
||||
private class GuavaPreconditionsMethod extends TaintPreservingCallable {
|
||||
GuavaPreconditionsMethod() {
|
||||
this.getDeclaringType() instanceof TypeGuavaPreconditions and
|
||||
this.hasName("checkNotNull")
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int src) { src = 0 }
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/** Definitions of flow steps through the various string utility functions in the Guava framework. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
|
||||
/**
|
||||
* The class `com.google.common.base.Strings`.
|
||||
*/
|
||||
class TypeGuavaStrings extends Class {
|
||||
TypeGuavaStrings() { this.hasQualifiedName("com.google.common.base", "Strings") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The class `com.google.common.base.Joiner`.
|
||||
*/
|
||||
class TypeGuavaJoiner extends Class {
|
||||
TypeGuavaJoiner() { this.hasQualifiedName("com.google.common.base", "Joiner") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The nested class `Joiner.MapJoiner`.
|
||||
*/
|
||||
class TypeGuavaMapJoiner extends NestedClass {
|
||||
TypeGuavaMapJoiner() {
|
||||
this.getEnclosingType() instanceof TypeGuavaJoiner and
|
||||
this.hasName("MapJoiner")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class `com.google.common.base.Splitter`.
|
||||
*/
|
||||
class TypeGuavaSplitter extends Class {
|
||||
TypeGuavaSplitter() { this.hasQualifiedName("com.google.common.base", "Splitter") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The nested class `Splitter.MapSplitter`.
|
||||
*/
|
||||
class TypeGuavaMapSplitter extends NestedClass {
|
||||
TypeGuavaMapSplitter() {
|
||||
this.getEnclosingType() instanceof TypeGuavaSplitter and
|
||||
this.hasName("MapSplitter")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint preserving method on `com.google.common.base.Strings`.
|
||||
*/
|
||||
private class GuavaStringsTaintPreservingMethod extends TaintPreservingCallable {
|
||||
GuavaStringsTaintPreservingMethod() {
|
||||
this.getDeclaringType() instanceof TypeGuavaStrings and
|
||||
// static String emptyToNull(String string)
|
||||
// static String nullToEmpty(String string)
|
||||
// static String padStart(String string, int minLength, char padChar)
|
||||
// static String padEnd(String string, int minLength, char padChar)
|
||||
// static String repeat(String string, int count)
|
||||
// static String lenientFormat(String template, Object ... args)
|
||||
this.hasName(["emptyToNull", "nullToEmpty", "padStart", "padEnd", "repeat", "lenientFormat"])
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int src) {
|
||||
src = 0
|
||||
or
|
||||
this.hasName("lenientFormat") and
|
||||
src = [0 .. getNumberOfParameters()]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method of `Joiner` or `MapJoiner`.
|
||||
*/
|
||||
private class GuavaJoinerMethod extends Method {
|
||||
GuavaJoinerMethod() {
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeGuavaJoiner or
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeGuavaMapJoiner
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that builds a `Joiner` or `MapJoiner`.
|
||||
*/
|
||||
private class GuavaJoinerBuilderMethod extends GuavaJoinerMethod, TaintPreservingCallable {
|
||||
GuavaJoinerBuilderMethod() {
|
||||
// static Joiner on(char separator)
|
||||
// static Joiner on(String separator)
|
||||
// Joiner skipNulls()
|
||||
// Joiner useForNull(String nullText)
|
||||
// Joiner.MapJoiner withKeyValueSeparator(char keyValueSeparator)
|
||||
// Joiner.MapJoiner withKeyValueSeparator(String keyValueSeparator)
|
||||
// Joiner.MapJoiner useForNull(String nullText) [on MapJoiner]
|
||||
this.hasName(["on", "skipNulls", "useForNull", "withKeyValueSeparator"])
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int src) {
|
||||
src = 0
|
||||
or
|
||||
src = -1 and not isStatic()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `appendTo` method on `Joiner` or `MapJoiner`.
|
||||
*/
|
||||
private class GuavaJoinerAppendToMethod extends GuavaJoinerMethod, TaintPreservingCallable {
|
||||
GuavaJoinerAppendToMethod() {
|
||||
// <A extends Appendable> A appendTo(A appendable, Iterable<?> parts)
|
||||
// <A extends Appendable> A appendTo(A appendable, Iterator<?> parts)
|
||||
// <A extends Appendable> A appendTo(A appendable, Object[] parts)
|
||||
// <A extends Appendable> A appendTo(A appendable, Object first, Object second, Object... rest)
|
||||
// StringBuilder appendTo(StringBuilder builder, Iterable<?> parts)
|
||||
// StringBuilder appendTo(StringBuilder builder, Iterator<?> parts)
|
||||
// StringBuilder appendTo(StringBuilder builder, Object[] parts)
|
||||
// StringBuilder appendTo(StringBuilder builder, Object first, Object second, Object... rest)
|
||||
// <A extends Appendable> A appendTo(A appendable, Iterable<? extends Map.Entry<?,?>> entries) [on MapJoiner]
|
||||
// <A extends Appendable> A appendTo(A appendable, Iterator<? extends Map.Entry<?,?>> parts)
|
||||
// <A extends Appendable> A appendTo(A appendable, Map<?,?> map)
|
||||
// StringBuilder appendTo(StringBuilder builder, Iterable<? extends Map.Entry<?,?>> entries)
|
||||
// StringBuilder appendTo(StringBuilder builder, Iterator<? extends Map.Entry<?,?>> entries)
|
||||
// StringBuilder appendTo(StringBuilder builder, Map<?,?> map)
|
||||
this.hasName("appendTo")
|
||||
}
|
||||
|
||||
override predicate transfersTaint(int src, int sink) {
|
||||
src = [-1 .. getNumberOfParameters()] and
|
||||
src != sink and
|
||||
sink = 0
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int src) { src = [-1 .. getNumberOfParameters()] }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `join` method on `Joiner` or `MapJoiner`.
|
||||
*/
|
||||
private class GuavaJoinMethod extends GuavaJoinerMethod, TaintPreservingCallable {
|
||||
GuavaJoinMethod() {
|
||||
// String join(Iterable<?> parts)
|
||||
// String join(Iterator<?> parts)
|
||||
// String join(Object[] parts)
|
||||
// String join(Object first, Object second, Object... rest)
|
||||
// String join(Iterable<? extends Map.Entry<?,?>> entries) [on MapJoiner]
|
||||
// String join(Iterator<? extends Map.Entry<?,?>> entries)
|
||||
// String join(Map<?,?> map)
|
||||
this.hasName("join")
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int src) { src = [-1 .. getNumberOfParameters()] }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method of `Splitter` or `MapSplitter` that splits its input string.
|
||||
*/
|
||||
private class GuavaSplitMethod extends TaintPreservingCallable {
|
||||
GuavaSplitMethod() {
|
||||
(
|
||||
this.getDeclaringType() instanceof TypeGuavaSplitter
|
||||
or
|
||||
this.getDeclaringType() instanceof TypeGuavaMapSplitter
|
||||
) and
|
||||
// Iterable<String> split(CharSequence sequence)
|
||||
// List<String> splitToList(CharSequence sequence)
|
||||
// Stream<String> splitToStream(CharSequence sequence)
|
||||
// Map<String,String> split(CharSequence sequence) [on MapSplitter]
|
||||
this.hasName(["split", "splitToList", "splitToStream"])
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int src) { src = 0 }
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Joiner;
|
||||
package com.google.common.base;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
class TestStrings {
|
||||
class TestBase {
|
||||
String taint() { return "tainted"; }
|
||||
|
||||
void sink(Object o) {}
|
||||
@@ -59,4 +56,8 @@ class TestStrings {
|
||||
m.put("k2", x);
|
||||
sink(safeJoiner.withKeyValueSeparator("=").join(m)); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test4() {
|
||||
sink(Preconditions.checkNotNull(taint())); // $numTaintFlow=1
|
||||
}
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
| literals/Literals.java:11:22:11:25 | true |
|
||||
| literals/Literals.java:11:22:11:25 | true | true | true |
|
||||
| literals/Literals.java:16:3:16:6 | true | true | true |
|
||||
| literals/Literals.java:17:3:17:7 | false | false | false |
|
||||
|
||||
@@ -2,4 +2,4 @@ import semmle.code.java.Expr
|
||||
|
||||
from BooleanLiteral lit
|
||||
where lit.getCompilationUnit().fromSource()
|
||||
select lit
|
||||
select lit, lit.getValue(), lit.getBooleanValue()
|
||||
|
||||
@@ -1 +1,10 @@
|
||||
| literals/Literals.java:12:22:12:24 | 'x' |
|
||||
| literals/Literals.java:12:22:12:24 | 'x' | x |
|
||||
| literals/Literals.java:21:3:21:5 | 'a' | a |
|
||||
| literals/Literals.java:22:3:22:10 | '\\u0061' | a |
|
||||
| literals/Literals.java:23:3:23:10 | '\\u0000' | \u0000 |
|
||||
| literals/Literals.java:24:3:24:6 | '\\0' | \u0000 |
|
||||
| literals/Literals.java:25:3:25:6 | '\\n' | \n |
|
||||
| literals/Literals.java:26:3:26:6 | '\\0' | \u0000 |
|
||||
| literals/Literals.java:27:3:27:6 | '\\\\' | \\ |
|
||||
| literals/Literals.java:28:3:28:6 | '\\'' | ' |
|
||||
| literals/Literals.java:29:3:29:8 | '\\123' | S |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.java.Expr
|
||||
|
||||
from CharacterLiteral lit
|
||||
select lit
|
||||
select lit, lit.getValue()
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
| literals/Literals.java:10:22:10:27 | 456.0D |
|
||||
| literals/Literals.java:10:22:10:27 | 456.0D | 456.0 | 456.0 |
|
||||
| literals/Literals.java:33:3:33:5 | 0.0 | 0.0 | 0.0 |
|
||||
| literals/Literals.java:34:3:34:4 | 0d | 0.0 | 0.0 |
|
||||
| literals/Literals.java:35:3:35:5 | .0d | 0.0 | 0.0 |
|
||||
| literals/Literals.java:36:3:36:4 | .0 | 0.0 | 0.0 |
|
||||
| literals/Literals.java:37:4:37:6 | 0.d | 0.0 | 0.0 |
|
||||
| literals/Literals.java:38:4:38:6 | 0.d | 0.0 | 0.0 |
|
||||
| literals/Literals.java:39:3:39:22 | 1.234567890123456789 | 1.2345678901234567 | 1.2345678901234567 |
|
||||
| literals/Literals.java:40:3:40:24 | 1.55555555555555555555 | 1.5555555555555556 | 1.5555555555555556 |
|
||||
| literals/Literals.java:42:3:42:5 | 1e1 | 10.0 | 10.0 |
|
||||
| literals/Literals.java:43:3:43:24 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 |
|
||||
| literals/Literals.java:44:4:44:25 | 1.7976931348623157E308 | 1.7976931348623157E308 | 1.7976931348623157E308 |
|
||||
| literals/Literals.java:45:3:45:28 | 0x1.f_ffff_ffff_ffffP+1023 | 1.7976931348623157E308 | 1.7976931348623157E308 |
|
||||
| literals/Literals.java:46:3:46:10 | 4.9e-324 | 4.9E-324 | 4.9E-324 |
|
||||
| literals/Literals.java:47:3:47:28 | 0x0.0_0000_0000_0001P-1022 | 4.9E-324 | 4.9E-324 |
|
||||
| literals/Literals.java:48:3:48:13 | 0x1.0P-1074 | 4.9E-324 | 4.9E-324 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.java.Expr
|
||||
|
||||
from DoubleLiteral lit
|
||||
select lit
|
||||
select lit, lit.getValue(), lit.getDoubleValue()
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
| literals/Literals.java:9:22:9:27 | 123.0F |
|
||||
| literals/Literals.java:9:22:9:27 | 123.0F | 123.0 | 123.0 |
|
||||
| literals/Literals.java:52:3:52:6 | 0.0f | 0.0 | 0.0 |
|
||||
| literals/Literals.java:53:3:53:4 | 0f | 0.0 | 0.0 |
|
||||
| literals/Literals.java:54:3:54:5 | .0f | 0.0 | 0.0 |
|
||||
| literals/Literals.java:55:4:55:6 | 0.f | 0.0 | 0.0 |
|
||||
| literals/Literals.java:56:4:56:6 | 0.f | 0.0 | 0.0 |
|
||||
| literals/Literals.java:57:3:57:10 | 1_0_0.0f | 100.0 | 100.0 |
|
||||
| literals/Literals.java:58:3:58:23 | 1.234567890123456789f | 1.2345679 | 1.2345679 |
|
||||
| literals/Literals.java:59:3:59:25 | 1.55555555555555555555f | 1.5555556 | 1.5555556 |
|
||||
| literals/Literals.java:61:3:61:6 | 1e1f | 10.0 | 10.0 |
|
||||
| literals/Literals.java:62:3:62:15 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 |
|
||||
| literals/Literals.java:63:4:63:16 | 3.4028235e38f | 3.4028235E38 | 3.4028235E38 |
|
||||
| literals/Literals.java:64:3:64:18 | 0x1.fffffeP+127f | 3.4028235E38 | 3.4028235E38 |
|
||||
| literals/Literals.java:65:3:65:10 | 1.4e-45f | 1.4E-45 | 1.4E-45 |
|
||||
| literals/Literals.java:66:3:66:18 | 0x0.000002P-126f | 1.4E-45 | 1.4E-45 |
|
||||
| literals/Literals.java:67:3:67:13 | 0x1.0P-149f | 1.4E-45 | 1.4E-45 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.java.Expr
|
||||
|
||||
from FloatingPointLiteral lit
|
||||
select lit
|
||||
select lit, lit.getValue(), lit.getFloatValue()
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
| literals/Literals.java:7:22:7:24 | 123 |
|
||||
| literals/Literals.java:14:16:14:26 | -2147483648 |
|
||||
| literals/Literals.java:16:21:16:30 | 2147483647 |
|
||||
| literals/Literals.java:18:20:18:29 | 0x80000000 |
|
||||
| literals/Literals.java:20:10:20:11 | 23 |
|
||||
| literals/Literals.java:20:15:20:16 | 19 |
|
||||
| literals/Literals.java:21:10:21:11 | 23 |
|
||||
| literals/Literals.java:21:15:21:16 | 19 |
|
||||
| literals/Literals.java:7:22:7:24 | 123 | 123 | 123 |
|
||||
| literals/Literals.java:71:3:71:3 | 0 | 0 | 0 |
|
||||
| literals/Literals.java:72:3:72:5 | 0_0 | 0 | 0 |
|
||||
| literals/Literals.java:73:3:73:7 | 0___0 | 0 | 0 |
|
||||
| literals/Literals.java:74:3:74:6 | 0_12 | 10 | 10 |
|
||||
| literals/Literals.java:75:3:75:7 | 0X012 | 18 | 18 |
|
||||
| literals/Literals.java:76:3:76:10 | 0xaBcDeF | 11259375 | 11259375 |
|
||||
| literals/Literals.java:77:3:77:6 | 0B11 | 3 | 3 |
|
||||
| literals/Literals.java:78:3:78:12 | 0x80000000 | -2147483648 | -2147483648 |
|
||||
| literals/Literals.java:79:3:79:12 | 2147483647 | 2147483647 | 2147483647 |
|
||||
| literals/Literals.java:80:3:80:13 | -2147483648 | -2147483648 | -2147483648 |
|
||||
| literals/Literals.java:82:3:82:13 | 0x7fff_ffff | 2147483647 | 2147483647 |
|
||||
| literals/Literals.java:83:3:83:16 | 0177_7777_7777 | 2147483647 | 2147483647 |
|
||||
| literals/Literals.java:84:3:84:43 | 0b0111_1111_1111_1111_1111_1111_1111_1111 | 2147483647 | 2147483647 |
|
||||
| literals/Literals.java:85:3:85:13 | 0x8000_0000 | -2147483648 | -2147483648 |
|
||||
| literals/Literals.java:86:3:86:16 | 0200_0000_0000 | -2147483648 | -2147483648 |
|
||||
| literals/Literals.java:87:3:87:43 | 0b1000_0000_0000_0000_0000_0000_0000_0000 | -2147483648 | -2147483648 |
|
||||
| literals/Literals.java:88:3:88:13 | 0xffff_ffff | -1 | -1 |
|
||||
| literals/Literals.java:89:3:89:16 | 0377_7777_7777 | -1 | -1 |
|
||||
| literals/Literals.java:90:3:90:43 | 0b1111_1111_1111_1111_1111_1111_1111_1111 | -1 | -1 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.java.Expr
|
||||
|
||||
from IntegerLiteral lit
|
||||
select lit
|
||||
select lit, lit.getValue(), lit.getIntValue()
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
| literals/Literals.java:8:22:8:25 | 456L |
|
||||
| literals/Literals.java:15:18:15:38 | -9223372036854775808l |
|
||||
| literals/Literals.java:17:23:17:42 | 9223372036854775807l |
|
||||
| literals/Literals.java:19:22:19:40 | 0x8000000000000000L |
|
||||
| literals/Literals.java:8:22:8:25 | 456L | 456 |
|
||||
| literals/Literals.java:94:3:94:4 | 0l | 0 |
|
||||
| literals/Literals.java:95:3:95:4 | 0L | 0 |
|
||||
| literals/Literals.java:96:3:96:6 | 0_0L | 0 |
|
||||
| literals/Literals.java:97:3:97:8 | 0___0L | 0 |
|
||||
| literals/Literals.java:98:3:98:7 | 0_12L | 10 |
|
||||
| literals/Literals.java:99:3:99:8 | 0X012L | 18 |
|
||||
| literals/Literals.java:100:3:100:11 | 0xaBcDeFL | 11259375 |
|
||||
| literals/Literals.java:101:3:101:7 | 0B11L | 3 |
|
||||
| literals/Literals.java:102:3:102:22 | 9223372036854775807L | 9223372036854775807 |
|
||||
| literals/Literals.java:103:3:103:23 | -9223372036854775808L | -9223372036854775808 |
|
||||
| literals/Literals.java:105:3:105:24 | 0x7fff_ffff_ffff_ffffL | 9223372036854775807 |
|
||||
| literals/Literals.java:106:3:106:30 | 07_7777_7777_7777_7777_7777L | 9223372036854775807 |
|
||||
| literals/Literals.java:107:3:107:84 | 0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L | 9223372036854775807 |
|
||||
| literals/Literals.java:108:3:108:24 | 0x8000_0000_0000_0000L | -9223372036854775808 |
|
||||
| literals/Literals.java:109:3:109:31 | 010_0000_0000_0000_0000_0000L | -9223372036854775808 |
|
||||
| literals/Literals.java:110:3:110:84 | 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L | -9223372036854775808 |
|
||||
| literals/Literals.java:111:3:111:24 | 0xffff_ffff_ffff_ffffL | -1 |
|
||||
| literals/Literals.java:112:3:112:31 | 017_7777_7777_7777_7777_7777L | -1 |
|
||||
| literals/Literals.java:113:3:113:84 | 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L | -1 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.java.Expr
|
||||
|
||||
from LongLiteral lit
|
||||
select lit
|
||||
select lit, lit.getValue()
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
| literals/Literals.java:6:22:6:37 | "literal string" |
|
||||
| literals/Literals.java:22:22:22:38 | "hello" + "world" |
|
||||
| literals/Literals.java:23:24:23:47 | "hello" + ", " + "world" |
|
||||
| literals/Literals.java:24:23:24:52 | "hello" + ", " + "world" + "!" |
|
||||
| literals/Literals.java:25:22:25:36 | "hello,\\tworld" |
|
||||
| literals/Literals.java:26:30:26:48 | "hello,\\u0009world" |
|
||||
| literals/Literals.java:6:22:6:37 | "literal string" | literal string | literal string |
|
||||
| literals/Literals.java:117:3:117:19 | "hello" + "world" | helloworld | helloworld |
|
||||
| literals/Literals.java:118:3:118:17 | "hello,\\tworld" | hello,\tworld | hello,\tworld |
|
||||
| literals/Literals.java:119:3:119:21 | "hello,\\u0009world" | hello,\tworld | hello,\tworld |
|
||||
| literals/Literals.java:120:3:120:10 | "\\u0061" | a | a |
|
||||
| literals/Literals.java:121:3:121:6 | "\\0" | \u0000 | \u0000 |
|
||||
| literals/Literals.java:122:3:122:9 | "\\0000" | \u00000 | \u00000 |
|
||||
| literals/Literals.java:123:3:123:6 | "\\"" | " | " |
|
||||
| literals/Literals.java:124:3:124:6 | "\\'" | ' | ' |
|
||||
| literals/Literals.java:125:3:125:6 | "\\n" | \n | \n |
|
||||
| literals/Literals.java:126:3:126:6 | "\\\\" | \\ | \\ |
|
||||
| literals/Literals.java:127:3:127:13 | "test \\123" | test S | test S |
|
||||
| literals/Literals.java:128:3:128:9 | "\\1234" | S4 | S4 |
|
||||
| literals/Literals.java:129:3:129:13 | "\\u0061567" | a567 | a567 |
|
||||
| literals/Literals.java:130:3:130:13 | "\\u1234567" | \u1234567 | \u1234567 |
|
||||
| literals/Literals.java:131:3:131:18 | "\\uaBcDeF\\u0aB1" | \uabcdeF\u0ab1 | \uabcdeF\u0ab1 |
|
||||
| literals/Literals.java:132:3:132:16 | "\\uD800\\uDC00" | \ud800\udc00 | \ud800\udc00 |
|
||||
| literals/Literals.java:134:3:134:10 | "\\uD800" | ? | ? |
|
||||
| literals/Literals.java:135:3:135:10 | "\\uDC00" | ? | ? |
|
||||
| literals/Literals.java:136:3:136:31 | "hello\\uD800hello\\uDC00world" | hello?hello?world | hello?hello?world |
|
||||
|
||||
@@ -2,4 +2,4 @@ import semmle.code.java.Expr
|
||||
|
||||
from StringLiteral lit
|
||||
where lit.getFile().(CompilationUnit).fromSource()
|
||||
select lit
|
||||
select lit, lit.getValue(), lit.getRepresentedString()
|
||||
|
||||
@@ -11,17 +11,128 @@ public class Literals {
|
||||
System.out.println(true);
|
||||
System.out.println('x');
|
||||
}
|
||||
int min_int = -2147483648;
|
||||
long min_long = -9223372036854775808l;
|
||||
int neg_max_int = -2147483647;
|
||||
long neg_max_long = -9223372036854775807l;
|
||||
int alt_min_int = 0x80000000;
|
||||
long alt_min_long = 0x8000000000000000L;
|
||||
int i = 23 + 19;
|
||||
int j = 23 +19;
|
||||
String twostrings = "hello" + "world";
|
||||
String threestrings = "hello" + ", " + "world";
|
||||
String fourstrings = "hello" + ", " + "world" + "!";
|
||||
String escape_seq = "hello,\tworld";
|
||||
String unicode_escape_seq = "hello,\u0009world";
|
||||
|
||||
boolean[] booleans = {
|
||||
true,
|
||||
false
|
||||
};
|
||||
|
||||
char[] chars = {
|
||||
'a',
|
||||
'\u0061', // 'a'
|
||||
'\u0000',
|
||||
'\0',
|
||||
'\n',
|
||||
'\0',
|
||||
'\\',
|
||||
'\'',
|
||||
'\123' // octal escape sequence for 'S'
|
||||
};
|
||||
|
||||
double[] doubles = {
|
||||
0.0,
|
||||
0d,
|
||||
.0d,
|
||||
.0,
|
||||
-0.d,
|
||||
+0.d,
|
||||
1.234567890123456789,
|
||||
1.55555555555555555555,
|
||||
// From the JLS
|
||||
1e1,
|
||||
1.7976931348623157E308,
|
||||
-1.7976931348623157E308,
|
||||
0x1.f_ffff_ffff_ffffP+1023,
|
||||
4.9e-324,
|
||||
0x0.0_0000_0000_0001P-1022,
|
||||
0x1.0P-1074
|
||||
};
|
||||
|
||||
float[] floats = {
|
||||
0.0f,
|
||||
0f,
|
||||
.0f,
|
||||
-0.f,
|
||||
+0.f,
|
||||
1_0_0.0f,
|
||||
1.234567890123456789f,
|
||||
1.55555555555555555555f,
|
||||
// From the JLS
|
||||
1e1f,
|
||||
3.4028235e38f,
|
||||
-3.4028235e38f,
|
||||
0x1.fffffeP+127f,
|
||||
1.4e-45f,
|
||||
0x0.000002P-126f,
|
||||
0x1.0P-149f
|
||||
};
|
||||
|
||||
int[] ints = {
|
||||
0,
|
||||
0_0,
|
||||
0___0,
|
||||
0_12, // octal
|
||||
0X012, // hex
|
||||
0xaBcDeF, // hex
|
||||
0B11, // binary
|
||||
0x80000000,
|
||||
2147483647,
|
||||
-2147483648,
|
||||
// From the JLS
|
||||
0x7fff_ffff,
|
||||
0177_7777_7777, // octal
|
||||
0b0111_1111_1111_1111_1111_1111_1111_1111, // binary
|
||||
0x8000_0000,
|
||||
0200_0000_0000,
|
||||
0b1000_0000_0000_0000_0000_0000_0000_0000,
|
||||
0xffff_ffff,
|
||||
0377_7777_7777,
|
||||
0b1111_1111_1111_1111_1111_1111_1111_1111
|
||||
};
|
||||
|
||||
long[] longs = {
|
||||
0l,
|
||||
0L,
|
||||
0_0L,
|
||||
0___0L,
|
||||
0_12L, // octal
|
||||
0X012L, // hex
|
||||
0xaBcDeFL, // hex
|
||||
0B11L, // binary
|
||||
9223372036854775807L,
|
||||
-9223372036854775808L,
|
||||
// From the JLS
|
||||
0x7fff_ffff_ffff_ffffL,
|
||||
07_7777_7777_7777_7777_7777L, // octal
|
||||
0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L, // binary
|
||||
0x8000_0000_0000_0000L,
|
||||
010_0000_0000_0000_0000_0000L,
|
||||
0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L,
|
||||
0xffff_ffff_ffff_ffffL,
|
||||
017_7777_7777_7777_7777_7777L,
|
||||
0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L
|
||||
};
|
||||
|
||||
String[] strings = {
|
||||
"hello" + "world", // two separate literals
|
||||
"hello,\tworld",
|
||||
"hello,\u0009world",
|
||||
"\u0061", // 'a'
|
||||
"\0",
|
||||
"\0000",
|
||||
"\"",
|
||||
"\'",
|
||||
"\n",
|
||||
"\\",
|
||||
"test \123", // octal escape sequence for 'S'
|
||||
"\1234", // octal escape followed by '4'
|
||||
"\u0061567", // escape sequence for 'a' followed by "567"
|
||||
"\u1234567", // '\u1234' followed by "567"
|
||||
"\uaBcDeF\u0aB1", // '\uABCD' followed by "eF" followed by '\u0AB1'
|
||||
"\uD800\uDC00", // surrogate pair
|
||||
// Unpaired surrogates
|
||||
"\uD800",
|
||||
"\uDC00",
|
||||
"hello\uD800hello\uDC00world"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.base;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class Preconditions {
|
||||
public static void checkArgument(boolean expression) {
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean expression, @Nullable Object errorMessage) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean expression,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object @Nullable ... errorMessageArgs) {
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean b, @Nullable String errorMessageTemplate, char p1) {
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean b, @Nullable String errorMessageTemplate, int p1) {
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean b, @Nullable String errorMessageTemplate, long p1) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, int p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, int p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, int p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, int p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object p1,
|
||||
@Nullable Object p2,
|
||||
@Nullable Object p3) {
|
||||
}
|
||||
|
||||
public static void checkArgument(
|
||||
boolean b,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object p1,
|
||||
@Nullable Object p2,
|
||||
@Nullable Object p3,
|
||||
@Nullable Object p4) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean expression) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean expression, @Nullable Object errorMessage) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean expression,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object @Nullable ... errorMessageArgs) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, char p1) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, int p1) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, long p1) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, char p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, char p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, int p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, int p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, int p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, int p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkState(boolean b, @Nullable String errorMessageTemplate, long p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, long p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, char p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, int p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, long p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b, @Nullable String errorMessageTemplate, @Nullable Object p1, @Nullable Object p2) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object p1,
|
||||
@Nullable Object p2,
|
||||
@Nullable Object p3) {
|
||||
}
|
||||
|
||||
public static void checkState(
|
||||
boolean b,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object p1,
|
||||
@Nullable Object p2,
|
||||
@Nullable Object p3,
|
||||
@Nullable Object p4) {
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(T reference) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T reference, @Nullable Object errorMessage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T reference,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object @Nullable ... errorMessageArgs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, char p1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, int p1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, long p1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, @Nullable Object p1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, char p1, char p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, char p1, int p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, char p1, long p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, char p1, @Nullable Object p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, int p1, char p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, int p1, int p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, int p1, long p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, int p1, @Nullable Object p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, long p1, char p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, long p1, int p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, long p1, long p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, long p1, @Nullable Object p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, @Nullable Object p1, char p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, @Nullable Object p1, int p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, @Nullable Object p1, long p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj, @Nullable String errorMessageTemplate, @Nullable Object p1, @Nullable Object p2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object p1,
|
||||
@Nullable Object p2,
|
||||
@Nullable Object p3) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends @NonNull Object> T checkNotNull(
|
||||
T obj,
|
||||
@Nullable String errorMessageTemplate,
|
||||
@Nullable Object p1,
|
||||
@Nullable Object p2,
|
||||
@Nullable Object p3,
|
||||
@Nullable Object p4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int checkElementIndex(int index, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int checkElementIndex(int index, int size, @Nullable String desc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int checkPositionIndex(int index, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int checkPositionIndex(int index, int size, @Nullable String desc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void checkPositionIndexes(int start, int end, int size) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.checkerframework.checker.nullness.qual;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
public @interface NonNull {}
|
||||
@@ -1,2 +1,6 @@
|
||||
package org.checkerframework.checker.nullness.qual;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
public @interface Nullable {}
|
||||
Reference in New Issue
Block a user