Java: Autoformat.

This commit is contained in:
Anders Schack-Mulligen
2018-10-12 13:44:55 +02:00
parent 11279d4c83
commit 22c986af77
4 changed files with 162 additions and 139 deletions

View File

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

View File

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

View File

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

View File

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