mirror of
https://github.com/github/codeql.git
synced 2026-02-28 12:53:49 +01:00
Java: Autoformat.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about string formatting.
|
||||
*/
|
||||
|
||||
import java
|
||||
import dataflow.DefUse
|
||||
|
||||
@@ -8,7 +9,7 @@ import dataflow.DefUse
|
||||
* A library method that formats a number of its arguments according to a
|
||||
* format string.
|
||||
*/
|
||||
private abstract class FormatMethod extends Method {
|
||||
abstract private class FormatMethod extends Method {
|
||||
/** Gets the index of the format string argument. */
|
||||
abstract int getFormatStringIndex();
|
||||
}
|
||||
@@ -24,7 +25,8 @@ class StringFormatMethod extends FormatMethod {
|
||||
this.hasName("printf") or
|
||||
this.hasName("readLine") or
|
||||
this.hasName("readPassword")
|
||||
) and (
|
||||
) and
|
||||
(
|
||||
this.getDeclaringType().hasQualifiedName("java.lang", "String") or
|
||||
this.getDeclaringType().hasQualifiedName("java.io", "PrintStream") or
|
||||
this.getDeclaringType().hasQualifiedName("java.io", "PrintWriter") or
|
||||
@@ -34,11 +36,18 @@ class StringFormatMethod extends FormatMethod {
|
||||
}
|
||||
|
||||
override int getFormatStringIndex() {
|
||||
result = 0 and this.getSignature() = "format(java.lang.String,java.lang.Object[])" or
|
||||
result = 0 and this.getSignature() = "printf(java.lang.String,java.lang.Object[])" or
|
||||
result = 1 and this.getSignature() = "format(java.util.Locale,java.lang.String,java.lang.Object[])" or
|
||||
result = 1 and this.getSignature() = "printf(java.util.Locale,java.lang.String,java.lang.Object[])" or
|
||||
result = 0 and this.getSignature() = "readLine(java.lang.String,java.lang.Object[])" or
|
||||
result = 0 and this.getSignature() = "format(java.lang.String,java.lang.Object[])"
|
||||
or
|
||||
result = 0 and this.getSignature() = "printf(java.lang.String,java.lang.Object[])"
|
||||
or
|
||||
result = 1 and
|
||||
this.getSignature() = "format(java.util.Locale,java.lang.String,java.lang.Object[])"
|
||||
or
|
||||
result = 1 and
|
||||
this.getSignature() = "printf(java.util.Locale,java.lang.String,java.lang.Object[])"
|
||||
or
|
||||
result = 0 and this.getSignature() = "readLine(java.lang.String,java.lang.Object[])"
|
||||
or
|
||||
result = 0 and this.getSignature() = "readPassword(java.lang.String,java.lang.Object[])"
|
||||
}
|
||||
}
|
||||
@@ -65,12 +74,15 @@ class LoggerFormatMethod extends FormatMethod {
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TFmtSyntax = TFmtPrintf() or TFmtLogger()
|
||||
private newtype TFmtSyntax =
|
||||
TFmtPrintf() or
|
||||
TFmtLogger()
|
||||
|
||||
/** A syntax for format strings. */
|
||||
class FmtSyntax extends TFmtSyntax {
|
||||
string toString() {
|
||||
result = "printf (%) syntax" and this = TFmtPrintf() or
|
||||
result = "printf (%) syntax" and this = TFmtPrintf()
|
||||
or
|
||||
result = "logger ({}) syntax" and this = TFmtLogger()
|
||||
}
|
||||
}
|
||||
@@ -84,17 +96,19 @@ private predicate formatWrapper(Callable c, int fmtix, FmtSyntax syntax) {
|
||||
exists(Parameter fmt, Parameter args, Call fmtcall, int i |
|
||||
fmt = c.getParameter(fmtix) and
|
||||
fmt.getType() instanceof TypeString and
|
||||
args = c.getParameter(fmtix+1) and
|
||||
args = c.getParameter(fmtix + 1) and
|
||||
args.getType().(Array).getElementType() instanceof TypeObject and
|
||||
c.getNumberOfParameters() = fmtix+2 and
|
||||
c.getNumberOfParameters() = fmtix + 2 and
|
||||
fmtcall.getEnclosingCallable() = c and
|
||||
(
|
||||
formatWrapper(fmtcall.getCallee(), i, syntax) or
|
||||
fmtcall.getCallee().(StringFormatMethod).getFormatStringIndex() = i and syntax = TFmtPrintf() or
|
||||
formatWrapper(fmtcall.getCallee(), i, syntax)
|
||||
or
|
||||
fmtcall.getCallee().(StringFormatMethod).getFormatStringIndex() = i and syntax = TFmtPrintf()
|
||||
or
|
||||
fmtcall.getCallee().(LoggerFormatMethod).getFormatStringIndex() = i and syntax = TFmtLogger()
|
||||
) and
|
||||
fmtcall.getArgument(i) = fmt.getAnAccess() and
|
||||
fmtcall.getArgument(i+1) = args.getAnAccess()
|
||||
fmtcall.getArgument(i + 1) = args.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -114,19 +128,18 @@ class FormattingCall extends Call {
|
||||
}
|
||||
|
||||
FmtSyntax getSyntax() {
|
||||
this.getCallee() instanceof StringFormatMethod and result = TFmtPrintf() or
|
||||
this.getCallee() instanceof LoggerFormatMethod and result = TFmtLogger() or
|
||||
this.getCallee() instanceof StringFormatMethod and result = TFmtPrintf()
|
||||
or
|
||||
this.getCallee() instanceof LoggerFormatMethod and result = TFmtLogger()
|
||||
or
|
||||
formatWrapper(this.getCallee(), _, result)
|
||||
}
|
||||
|
||||
private Expr getLastArg() {
|
||||
exists(Expr last |
|
||||
last = this.getArgument(this.getNumArgument() - 1)
|
||||
|
|
||||
if this.hasExplicitVarargsArray() then
|
||||
result = last.(ArrayCreationExpr).getInit().getInit(getVarargsCount() - 1)
|
||||
else
|
||||
result = last
|
||||
exists(Expr last | last = this.getArgument(this.getNumArgument() - 1) |
|
||||
if this.hasExplicitVarargsArray()
|
||||
then result = last.(ArrayCreationExpr).getInit().getInit(getVarargsCount() - 1)
|
||||
else result = last
|
||||
)
|
||||
}
|
||||
|
||||
@@ -136,9 +149,7 @@ class FormattingCall extends Call {
|
||||
}
|
||||
|
||||
/** Gets the argument to this call in the position of the format string */
|
||||
Expr getFormatArgument() {
|
||||
result = this.getArgument(this.getFormatStringIndex())
|
||||
}
|
||||
Expr getFormatArgument() { result = this.getArgument(this.getFormatStringIndex()) }
|
||||
|
||||
/** Gets an argument to be formatted. */
|
||||
Expr getAnArgumentToBeFormatted() {
|
||||
@@ -157,19 +168,22 @@ class FormattingCall extends Call {
|
||||
|
||||
/** Gets the length of the varargs array if it can determined. */
|
||||
int getVarargsCount() {
|
||||
if this.hasExplicitVarargsArray() then
|
||||
if this.hasExplicitVarargsArray()
|
||||
then
|
||||
exists(Expr arg | arg = this.getArgument(1 + this.getFormatStringIndex()) |
|
||||
result = arg.(ArrayCreationExpr).getFirstDimensionSize() or
|
||||
result = arg.(VarAccess).getVariable().getAnAssignedValue().(ArrayCreationExpr).getFirstDimensionSize()
|
||||
result = arg
|
||||
.(VarAccess)
|
||||
.getVariable()
|
||||
.getAnAssignedValue()
|
||||
.(ArrayCreationExpr)
|
||||
.getFirstDimensionSize()
|
||||
)
|
||||
else
|
||||
result = this.getNumArgument() - this.getFormatStringIndex() - 1
|
||||
else result = this.getNumArgument() - this.getFormatStringIndex() - 1
|
||||
}
|
||||
|
||||
/** Gets a `FormatString` that is used by this call. */
|
||||
FormatString getAFormatString() {
|
||||
result.getAFormattingUse() = this
|
||||
}
|
||||
FormatString getAFormatString() { result.getAFormattingUse() = this }
|
||||
}
|
||||
|
||||
/** Holds if `m` calls `toString()` on its `i`th argument. */
|
||||
@@ -177,11 +191,14 @@ private predicate printMethod(Method m, int i) {
|
||||
exists(RefType t |
|
||||
t = m.getDeclaringType() and
|
||||
m.getParameterType(i) instanceof TypeObject
|
||||
|
|
||||
|
|
||||
(t.hasQualifiedName("java.io", "PrintWriter") or t.hasQualifiedName("java.io", "PrintStream")) and
|
||||
(m.hasName("print") or m.hasName("println"))
|
||||
or
|
||||
(t.hasQualifiedName("java.lang", "StringBuilder") or t.hasQualifiedName("java.lang", "StringBuffer")) and
|
||||
(
|
||||
t.hasQualifiedName("java.lang", "StringBuilder") or
|
||||
t.hasQualifiedName("java.lang", "StringBuffer")
|
||||
) and
|
||||
(m.hasName("append") or m.hasName("insert"))
|
||||
or
|
||||
t instanceof TypeString and m.hasName("valueOf")
|
||||
@@ -195,8 +212,10 @@ private predicate printMethod(Method m, int i) {
|
||||
predicate implicitToStringCall(Expr e) {
|
||||
not e.getType() instanceof TypeString and
|
||||
(
|
||||
exists(FormattingCall fmtcall | fmtcall.getAnArgumentToBeFormatted() = e) or
|
||||
exists(AddExpr add | add.getType() instanceof TypeString and add.getAnOperand() = e) or
|
||||
exists(FormattingCall fmtcall | fmtcall.getAnArgumentToBeFormatted() = e)
|
||||
or
|
||||
exists(AddExpr add | add.getType() instanceof TypeString and add.getAnOperand() = e)
|
||||
or
|
||||
exists(MethodAccess ma, Method m, int i |
|
||||
ma.getMethod() = m and
|
||||
ma.getArgument(i) = e and
|
||||
@@ -209,16 +228,15 @@ predicate implicitToStringCall(Expr e) {
|
||||
* A call to a `format` or `printf` method.
|
||||
*/
|
||||
class StringFormat extends MethodAccess, FormattingCall {
|
||||
StringFormat() {
|
||||
this.getCallee() instanceof StringFormatMethod
|
||||
}
|
||||
StringFormat() { this.getCallee() instanceof StringFormatMethod }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fmt` is used as part of a format string.
|
||||
*/
|
||||
private predicate formatStringFragment(Expr fmt) {
|
||||
any(FormattingCall call).getFormatArgument() = fmt or
|
||||
any(FormattingCall call).getFormatArgument() = fmt
|
||||
or
|
||||
exists(Expr e | formatStringFragment(e) |
|
||||
e.(VarAccess).getVariable().getAnAssignedValue() = fmt or
|
||||
e.(AddExpr).getLeftOperand() = fmt or
|
||||
@@ -238,33 +256,43 @@ private predicate formatStringFragment(Expr fmt) {
|
||||
private predicate formatStringValue(Expr e, string fmtvalue) {
|
||||
formatStringFragment(e) and
|
||||
(
|
||||
e.(StringLiteral).getRepresentedString() = fmtvalue or
|
||||
e.getType() instanceof IntegralType and fmtvalue = "1" or // dummy value
|
||||
e.getType() instanceof BooleanType and fmtvalue = "x" or // dummy value
|
||||
e.getType() instanceof EnumType and fmtvalue = "x" or // dummy value
|
||||
formatStringValue(e.(ParExpr).getExpr(), fmtvalue) or
|
||||
e.(StringLiteral).getRepresentedString() = fmtvalue
|
||||
or
|
||||
e.getType() instanceof IntegralType and fmtvalue = "1" // dummy value
|
||||
or
|
||||
e.getType() instanceof BooleanType and fmtvalue = "x" // dummy value
|
||||
or
|
||||
e.getType() instanceof EnumType and fmtvalue = "x" // dummy value
|
||||
or
|
||||
formatStringValue(e.(ParExpr).getExpr(), fmtvalue)
|
||||
or
|
||||
exists(Variable v |
|
||||
e = v.getAnAccess() and
|
||||
v.isFinal() and
|
||||
v.getType() instanceof TypeString and
|
||||
formatStringValue(v.getInitializer(), fmtvalue)
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(LocalVariableDecl v |
|
||||
e = v.getAnAccess() and
|
||||
not exists(AssignAddExpr aa | aa.getDest() = v.getAnAccess()) and
|
||||
1 = count(v.getAnAssignedValue()) and
|
||||
v.getType() instanceof TypeString and
|
||||
formatStringValue(v.getAnAssignedValue(), fmtvalue)
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(AddExpr add, string left, string right |
|
||||
add = e and
|
||||
add.getType() instanceof TypeString and
|
||||
formatStringValue(add.getLeftOperand(), left) and
|
||||
formatStringValue(add.getRightOperand(), right) and
|
||||
fmtvalue = left + right
|
||||
) or
|
||||
formatStringValue(e.(ConditionalExpr).getTrueExpr(), fmtvalue) or
|
||||
formatStringValue(e.(ConditionalExpr).getFalseExpr(), fmtvalue) or
|
||||
)
|
||||
or
|
||||
formatStringValue(e.(ConditionalExpr).getTrueExpr(), fmtvalue)
|
||||
or
|
||||
formatStringValue(e.(ConditionalExpr).getFalseExpr(), fmtvalue)
|
||||
or
|
||||
exists(Method getprop, MethodAccess ma, string prop |
|
||||
e = ma and
|
||||
ma.getMethod() = getprop and
|
||||
@@ -274,12 +302,13 @@ private predicate formatStringValue(Expr e, string fmtvalue) {
|
||||
ma.getAnArgument().(StringLiteral).getRepresentedString() = prop and
|
||||
(prop = "line.separator" or prop = "file.separator" or prop = "path.separator") and
|
||||
fmtvalue = "x" // dummy value
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(Field f |
|
||||
e = f.getAnAccess() and
|
||||
f.getDeclaringType().hasQualifiedName("java.io", "File") and
|
||||
fmtvalue = "x" // dummy value
|
||||
|
|
||||
|
|
||||
f.hasName("pathSeparator") or
|
||||
f.hasName("pathSeparatorChar") or
|
||||
f.hasName("separator") or
|
||||
@@ -292,17 +321,17 @@ private predicate formatStringValue(Expr e, string fmtvalue) {
|
||||
* A string that is used as the format string in a `FormattingCall`.
|
||||
*/
|
||||
class FormatString extends string {
|
||||
FormatString() {
|
||||
formatStringValue(_, this)
|
||||
}
|
||||
FormatString() { formatStringValue(_, this) }
|
||||
|
||||
/** Gets a `FormattingCall` that uses this as its format string. */
|
||||
FormattingCall getAFormattingUse() {
|
||||
exists(Expr fmt | formatStringValue(fmt, this) |
|
||||
result.getFormatArgument() = fmt or
|
||||
result.getFormatArgument() = fmt
|
||||
or
|
||||
exists(VariableAssign va |
|
||||
defUsePair(va, result.getFormatArgument()) and va.getSource() = fmt
|
||||
) or
|
||||
)
|
||||
or
|
||||
result.getFormatArgument().(FieldAccess).getField().getAnAssignedValue() = fmt
|
||||
)
|
||||
}
|
||||
@@ -321,9 +350,7 @@ class FormatString extends string {
|
||||
}
|
||||
|
||||
private class PrintfFormatString extends FormatString {
|
||||
PrintfFormatString() {
|
||||
this.getAFormattingUse().getSyntax() = TFmtPrintf()
|
||||
}
|
||||
PrintfFormatString() { this.getAFormattingUse().getSyntax() = TFmtPrintf() }
|
||||
|
||||
/**
|
||||
* Gets a boolean value that indicates whether the `%` character at index `i`
|
||||
@@ -331,10 +358,9 @@ private class PrintfFormatString extends FormatString {
|
||||
*/
|
||||
private boolean isEscapedPct(int i) {
|
||||
this.charAt(i) = "%" and
|
||||
if this.charAt(i-1) = "%" then
|
||||
result = this.isEscapedPct(i-1).booleanNot()
|
||||
else
|
||||
result = false
|
||||
if this.charAt(i - 1) = "%"
|
||||
then result = this.isEscapedPct(i - 1).booleanNot()
|
||||
else result = false
|
||||
}
|
||||
|
||||
/** Holds if the format specifier at index `i` is a reference to an argument. */
|
||||
@@ -342,7 +368,7 @@ private class PrintfFormatString extends FormatString {
|
||||
false = this.isEscapedPct(i) and
|
||||
this.charAt(i) = "%" and
|
||||
exists(string c |
|
||||
c = this.charAt(i+1) and
|
||||
c = this.charAt(i + 1) and
|
||||
c != "%" and
|
||||
c != "n"
|
||||
)
|
||||
@@ -354,7 +380,7 @@ private class PrintfFormatString extends FormatString {
|
||||
*/
|
||||
private predicate fmtSpecRefersToPrevious(int i) {
|
||||
this.fmtSpecIsRef(i) and
|
||||
"<" = this.charAt(i+1)
|
||||
"<" = this.charAt(i + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,11 +389,10 @@ private class PrintfFormatString extends FormatString {
|
||||
*/
|
||||
private int fmtSpecRefersToSpecificIndex(int i) {
|
||||
this.fmtSpecIsRef(i) and
|
||||
exists(string num |
|
||||
result = num.toInt()
|
||||
|
|
||||
num = this.charAt(i+1) and "$" = this.charAt(i+2) or
|
||||
num = this.charAt(i+1) + this.charAt(i+2) and "$" = this.charAt(i+3)
|
||||
exists(string num | result = num.toInt() |
|
||||
num = this.charAt(i + 1) and "$" = this.charAt(i + 2)
|
||||
or
|
||||
num = this.charAt(i + 1) + this.charAt(i + 2) and "$" = this.charAt(i + 3)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -383,22 +408,20 @@ private class PrintfFormatString extends FormatString {
|
||||
|
||||
override int getMaxFmtSpecIndex() {
|
||||
result = max(int ix |
|
||||
ix = fmtSpecRefersToSpecificIndex(_) or
|
||||
ix = count(int i | fmtSpecRefersToSequentialIndex(i))
|
||||
)
|
||||
ix = fmtSpecRefersToSpecificIndex(_) or
|
||||
ix = count(int i | fmtSpecRefersToSequentialIndex(i))
|
||||
)
|
||||
}
|
||||
|
||||
override int getASkippedFmtSpecIndex() {
|
||||
result in [1..getMaxFmtSpecIndex()] and
|
||||
result in [1 .. getMaxFmtSpecIndex()] and
|
||||
result > count(int i | fmtSpecRefersToSequentialIndex(i)) and
|
||||
not result = fmtSpecRefersToSpecificIndex(_)
|
||||
}
|
||||
}
|
||||
|
||||
private class LoggerFormatString extends FormatString {
|
||||
LoggerFormatString() {
|
||||
this.getAFormattingUse().getSyntax() = TFmtLogger()
|
||||
}
|
||||
LoggerFormatString() { this.getAFormattingUse().getSyntax() = TFmtLogger() }
|
||||
|
||||
/**
|
||||
* Gets a boolean value that indicates whether the `\` character at index `i`
|
||||
@@ -406,20 +429,17 @@ private class LoggerFormatString extends FormatString {
|
||||
*/
|
||||
private boolean isUnescapedBackslash(int i) {
|
||||
this.charAt(i) = "\\" and
|
||||
if this.charAt(i-1) = "\\" then
|
||||
result = this.isUnescapedBackslash(i-1).booleanNot()
|
||||
else
|
||||
result = true
|
||||
if this.charAt(i - 1) = "\\"
|
||||
then result = this.isUnescapedBackslash(i - 1).booleanNot()
|
||||
else result = true
|
||||
}
|
||||
|
||||
/** Holds if an unescaped placeholder `{}` occurs at index `i`. */
|
||||
private predicate fmtPlaceholder(int i) {
|
||||
this.charAt(i) = "{" and
|
||||
this.charAt(i+1) = "}" and
|
||||
not true = isUnescapedBackslash(i-1)
|
||||
this.charAt(i + 1) = "}" and
|
||||
not true = isUnescapedBackslash(i - 1)
|
||||
}
|
||||
|
||||
override int getMaxFmtSpecIndex() {
|
||||
result = count(int i | fmtPlaceholder(i))
|
||||
}
|
||||
override int getMaxFmtSpecIndex() { result = count(int i | fmtPlaceholder(i)) }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Provides classes representing various flow sources for taint tracking.
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
@@ -17,7 +18,7 @@ import semmle.code.java.frameworks.JaxWS
|
||||
import semmle.code.java.frameworks.android.Intent
|
||||
|
||||
/** Class for `tainted` user input. */
|
||||
abstract class UserInput extends DataFlow::Node {}
|
||||
abstract class UserInput extends DataFlow::Node { }
|
||||
|
||||
private predicate variableStep(Expr tracked, VarAccess sink) {
|
||||
exists(VariableAssign def |
|
||||
@@ -75,10 +76,7 @@ class RemoteUserInput extends UserInput {
|
||||
* In addition to the basic taint flow, this allows a path to end in a number
|
||||
* of steps through instance fields.
|
||||
*/
|
||||
deprecated
|
||||
predicate flowsTo(DataFlow::Node sink) {
|
||||
remoteUserInputFlow(this, sink)
|
||||
}
|
||||
deprecated predicate flowsTo(DataFlow::Node sink) { remoteUserInputFlow(this, sink) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,13 +84,15 @@ class RemoteUserInput extends UserInput {
|
||||
* through an instance field.
|
||||
*/
|
||||
private predicate localInstanceFieldStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
TaintTracking::localTaintStep(node1, node2) or
|
||||
TaintTracking::localTaintStep(node1, node2)
|
||||
or
|
||||
exists(InstanceField field |
|
||||
node1.asExpr() = field.getAnAssignedValue() or
|
||||
node1.asExpr() = field.getAnAssignedValue()
|
||||
or
|
||||
exists(Assignment assign | assign.getRhs() = node1.asExpr() |
|
||||
assign.getDest().(ArrayAccess).getArray() = field.getAnAccess()
|
||||
)
|
||||
|
|
||||
|
|
||||
node2.asExpr() = field.getAnAccess()
|
||||
)
|
||||
}
|
||||
@@ -102,19 +102,21 @@ private module RemoteUserInputFlow {
|
||||
private import semmle.code.java.security.SecurityTests
|
||||
private import semmle.code.java.security.Validation
|
||||
|
||||
deprecated
|
||||
class RemoteUserInputConfig extends Configuration {
|
||||
deprecated class RemoteUserInputConfig extends Configuration {
|
||||
RemoteUserInputConfig() { this = "FlowSources.qll:RemoteUserInputConfig" }
|
||||
override
|
||||
predicate isSource(DataFlow::Node source) { source instanceof RemoteUserInput }
|
||||
override
|
||||
predicate isSink(DataFlow::Node sink) { any() }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteUserInput }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { any() }
|
||||
|
||||
override int fieldFlowBranchLimit() { result = 0 }
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) {
|
||||
// Ignore paths through test code.
|
||||
node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or
|
||||
exists(ValidatedVariable var | node.asExpr() = var.getAnAccess())
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
TaintTracking::localAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
@@ -122,9 +124,9 @@ private module RemoteUserInputFlow {
|
||||
}
|
||||
|
||||
cached
|
||||
deprecated
|
||||
private predicate remoteUserInputFlow(RemoteUserInput src, DataFlow::Node sink) {
|
||||
any(RemoteUserInputFlow::RemoteUserInputConfig config).hasFlow(src, sink) or
|
||||
deprecated private predicate remoteUserInputFlow(RemoteUserInput src, DataFlow::Node sink) {
|
||||
any(RemoteUserInputFlow::RemoteUserInputConfig config).hasFlow(src, sink)
|
||||
or
|
||||
exists(DataFlow::Node mid |
|
||||
remoteUserInputFlow(src, mid) and
|
||||
localInstanceFieldStep(mid, sink)
|
||||
@@ -132,7 +134,7 @@ private predicate remoteUserInputFlow(RemoteUserInput src, DataFlow::Node sink)
|
||||
}
|
||||
|
||||
/** Input that may be controlled by a local user. */
|
||||
abstract class LocalUserInput extends UserInput {}
|
||||
abstract class LocalUserInput extends UserInput { }
|
||||
|
||||
class EnvInput extends LocalUserInput {
|
||||
EnvInput() {
|
||||
@@ -140,7 +142,9 @@ class EnvInput extends LocalUserInput {
|
||||
exists(MainMethod main | this.asParameter() = main.getParameter(0))
|
||||
or
|
||||
// Args4j arguments.
|
||||
exists(Field f | this.asExpr() = f.getAnAccess() | f.getAnAnnotation().getType().getQualifiedName() = "org.kohsuke.args4j.Argument")
|
||||
exists(Field f | this.asExpr() = f.getAnAccess() |
|
||||
f.getAnAnnotation().getType().getQualifiedName() = "org.kohsuke.args4j.Argument"
|
||||
)
|
||||
or
|
||||
// Results from various specific methods.
|
||||
this.asExpr().(MethodAccess).getMethod() instanceof EnvTaintedMethod
|
||||
@@ -149,18 +153,19 @@ class EnvInput extends LocalUserInput {
|
||||
exists(Field f | this.asExpr() = f.getAnAccess() | f instanceof SystemIn)
|
||||
or
|
||||
// Access to files.
|
||||
this.asExpr().(ConstructorCall).getConstructedType().hasQualifiedName("java.io", "FileInputStream")
|
||||
this
|
||||
.asExpr()
|
||||
.(ConstructorCall)
|
||||
.getConstructedType()
|
||||
.hasQualifiedName("java.io", "FileInputStream")
|
||||
}
|
||||
}
|
||||
|
||||
class DatabaseInput extends LocalUserInput {
|
||||
DatabaseInput() {
|
||||
this.asExpr().(MethodAccess).getMethod() instanceof ResultSetGetStringMethod
|
||||
}
|
||||
DatabaseInput() { this.asExpr().(MethodAccess).getMethod() instanceof ResultSetGetStringMethod }
|
||||
}
|
||||
|
||||
private
|
||||
class RemoteTaintedMethod extends Method {
|
||||
private class RemoteTaintedMethod extends Method {
|
||||
RemoteTaintedMethod() {
|
||||
this instanceof ServletRequestGetParameterMethod or
|
||||
this instanceof ServletRequestGetParameterMapMethod or
|
||||
@@ -190,8 +195,7 @@ class RemoteTaintedMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
class EnvTaintedMethod extends Method {
|
||||
private class EnvTaintedMethod extends Method {
|
||||
EnvTaintedMethod() {
|
||||
this instanceof MethodSystemGetenv or
|
||||
this instanceof PropertiesGetPropertyMethod or
|
||||
@@ -200,9 +204,7 @@ class EnvTaintedMethod extends Method {
|
||||
}
|
||||
|
||||
class TypeInetAddr extends RefType {
|
||||
TypeInetAddr() {
|
||||
this.getQualifiedName() = "java.net.InetAddress"
|
||||
}
|
||||
TypeInetAddr() { this.getQualifiedName() = "java.net.InetAddress" }
|
||||
}
|
||||
|
||||
class ReverseDNSMethod extends Method {
|
||||
@@ -218,10 +220,13 @@ class ReverseDNSMethod extends Method {
|
||||
/** Android `Intent` that may have come from a hostile application. */
|
||||
class AndroidIntentInput extends DataFlow::Node {
|
||||
AndroidIntentInput() {
|
||||
exists(MethodAccess ma, AndroidGetIntentMethod m | ma.getMethod().overrides*(m) and
|
||||
exists(MethodAccess ma, AndroidGetIntentMethod m |
|
||||
ma.getMethod().overrides*(m) and
|
||||
this.asExpr() = ma
|
||||
) or
|
||||
exists(Method m, AndroidReceiveIntentMethod rI | m.overrides*(rI) and
|
||||
)
|
||||
or
|
||||
exists(Method m, AndroidReceiveIntentMethod rI |
|
||||
m.overrides*(rI) and
|
||||
this.asParameter() = m.getParameter(1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,12 +7,10 @@ private import semmle.code.java.controlflow.Dominance
|
||||
*
|
||||
* A basic block that terminates in a condition, splitting the subsequent control flow.
|
||||
*/
|
||||
deprecated
|
||||
class ConditionBlock = Guards::ConditionBlock;
|
||||
deprecated class ConditionBlock = Guards::ConditionBlock;
|
||||
|
||||
/** Holds if `n` updates the locally scoped variable `v`. */
|
||||
deprecated
|
||||
predicate variableUpdate(ControlFlowNode n, LocalScopeVariable v) {
|
||||
deprecated predicate variableUpdate(ControlFlowNode n, LocalScopeVariable v) {
|
||||
exists(VariableUpdate a | a = n | a.getDestVar() = v)
|
||||
}
|
||||
|
||||
@@ -34,7 +32,9 @@ deprecated private predicate relevantVar(ConditionBlock cb, LocalScopeVariable v
|
||||
}
|
||||
|
||||
/** Blocks controlled by the condition in `cb` for which `v` is unchanged. */
|
||||
deprecated private predicate controlsBlockWithSameVar(ConditionBlock cb, boolean testIsTrue, LocalScopeVariable v, BasicBlock controlled) {
|
||||
deprecated private predicate controlsBlockWithSameVar(
|
||||
ConditionBlock cb, boolean testIsTrue, LocalScopeVariable v, BasicBlock controlled
|
||||
) {
|
||||
cb.controls(controlled, testIsTrue) and
|
||||
relevantVar(cb, v) and
|
||||
not needPhiNode(controlled, v) and
|
||||
@@ -55,11 +55,15 @@ deprecated private predicate controlsBlockWithSameVar(ConditionBlock cb, boolean
|
||||
* Statements controlled by the condition in `s` for which `v` is unchanged (`v` is the same SSA
|
||||
* variable in both `s` and `controlled`). The condition in `s` must contain an access of `v`.
|
||||
*/
|
||||
deprecated
|
||||
predicate controlsNodeWithSameVar(ConditionNode cn, boolean testIsTrue, LocalScopeVariable v, ControlFlowNode controlled) {
|
||||
deprecated predicate controlsNodeWithSameVar(
|
||||
ConditionNode cn, boolean testIsTrue, LocalScopeVariable v, ControlFlowNode controlled
|
||||
) {
|
||||
exists(ConditionBlock cb, BasicBlock controlledBB, int i |
|
||||
cb.getConditionNode() = cn and
|
||||
controlsBlockWithSameVar(cb, testIsTrue, v, controlledBB) and
|
||||
controlled = controlledBB.getNode(i) and
|
||||
not exists(ControlFlowNode update, int j | update = controlledBB.getNode(j) and j < i and variableUpdate(update, v)))
|
||||
not exists(ControlFlowNode update, int j |
|
||||
update = controlledBB.getNode(j) and j < i and variableUpdate(update, v)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,31 +14,25 @@
|
||||
*
|
||||
* This creates a route to the `ConsumeMdb` class for messages sent to "activemq:queue:sayhello".
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.Reflection
|
||||
import semmle.code.java.frameworks.spring.Spring
|
||||
|
||||
|
||||
library class CamelAnnotation extends Annotation {
|
||||
CamelAnnotation() {
|
||||
getType().getPackage().hasName("org.apache.camel")
|
||||
}
|
||||
CamelAnnotation() { getType().getPackage().hasName("org.apache.camel") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An annotation indicating that the annotated method is called by Apache Camel.
|
||||
*/
|
||||
class CamelConsumeAnnotation extends CamelAnnotation {
|
||||
CamelConsumeAnnotation() {
|
||||
getType().hasName("Consume")
|
||||
}
|
||||
CamelConsumeAnnotation() { getType().hasName("Consume") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that may be called by Apache Camel in response to a message.
|
||||
*/
|
||||
class CamelConsumeMethod extends Method {
|
||||
CamelConsumeMethod() {
|
||||
getAnAnnotation() instanceof CamelConsumeAnnotation
|
||||
}
|
||||
CamelConsumeMethod() { getAnAnnotation() instanceof CamelConsumeAnnotation }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user