Merge branch 'main' into emptyRedos

This commit is contained in:
Rasmus Wriedt Larsen
2021-07-15 18:21:29 +02:00
154 changed files with 2721 additions and 1045 deletions

View File

@@ -0,0 +1,4 @@
lgtm,codescanning
* The `StackVariableReachability` library now ignores some paths that contain an infeasible combination
of conditionals. These improvements primarily affect the queries `cpp/uninitialized-local` and
`cpp/use-after-free`.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The 'Wrong type of arguments to formatting function' (cpp/wrong-type-format-argument) query is now more accepting of the string and character formatting differences between Microsoft and non-Microsoft platforms. There are now fewer false positive results.

View File

@@ -19,28 +19,32 @@ import cpp
* Holds if the argument corresponding to the `pos` conversion specifier
* of `ffc` is expected to have type `expected`.
*/
pragma[noopt]
private predicate formattingFunctionCallExpectedType(
FormattingFunctionCall ffc, int pos, Type expected
) {
exists(FormattingFunction f, int i, FormatLiteral fl |
ffc instanceof FormattingFunctionCall and
ffc.getTarget() = f and
f.getFormatParameterIndex() = i and
ffc.getArgument(i) = fl and
fl.getConversionType(pos) = expected
)
ffc.getFormat().(FormatLiteral).getConversionType(pos) = expected
}
/**
* Holds if the argument corresponding to the `pos` conversion specifier
* of `ffc` is expected to have type `expected` and the corresponding
* argument `arg` has type `actual`.
* of `ffc` could alternatively have type `expected`, for example on a different
* platform.
*/
private predicate formattingFunctionCallAlternateType(
FormattingFunctionCall ffc, int pos, Type expected
) {
ffc.getFormat().(FormatLiteral).getConversionTypeAlternate(pos) = expected
}
/**
* Holds if the argument corresponding to the `pos` conversion specifier
* of `ffc` is `arg` and has type `actual`.
*/
pragma[noopt]
predicate formatArgType(FormattingFunctionCall ffc, int pos, Type expected, Expr arg, Type actual) {
predicate formattingFunctionCallActualType(
FormattingFunctionCall ffc, int pos, Expr arg, Type actual
) {
exists(Expr argConverted |
formattingFunctionCallExpectedType(ffc, pos, expected) and
ffc.getConversionArgument(pos) = arg and
argConverted = arg.getFullyConverted() and
actual = argConverted.getType()
@@ -72,7 +76,8 @@ class ExpectedType extends Type {
ExpectedType() {
exists(Type t |
(
formatArgType(_, _, t, _, _) or
formattingFunctionCallExpectedType(_, _, t) or
formattingFunctionCallAlternateType(_, _, t) or
formatOtherArgType(_, _, t, _, _)
) and
this = t.getUnspecifiedType()
@@ -91,7 +96,11 @@ class ExpectedType extends Type {
*/
predicate trivialConversion(ExpectedType expected, Type actual) {
exists(Type exp, Type act |
formatArgType(_, _, exp, _, act) and
(
formattingFunctionCallExpectedType(_, _, exp) or
formattingFunctionCallAlternateType(_, _, exp)
) and
formattingFunctionCallActualType(_, _, _, act) and
expected = exp.getUnspecifiedType() and
actual = act.getUnspecifiedType()
) and
@@ -146,9 +155,13 @@ int sizeof_IntType() { exists(IntType it | result = it.getSize()) }
from FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual
where
(
formatArgType(ffc, n, expected, arg, actual) and
formattingFunctionCallExpectedType(ffc, n, expected) and
formattingFunctionCallActualType(ffc, n, arg, actual) and
not exists(Type anyExpected |
formatArgType(ffc, n, anyExpected, arg, actual) and
(
formattingFunctionCallExpectedType(ffc, n, anyExpected) or
formattingFunctionCallAlternateType(ffc, n, anyExpected)
) and
trivialConversion(anyExpected.getUnspecifiedType(), actual.getUnspecifiedType())
)
or

View File

@@ -0,0 +1,12 @@
intA = ++intA + 1; // BAD: undefined behavior when changing variable `intA`
...
intA++;
intA = intA + 1; // GOOD: correct design
...
char * buff;
...
if(funcAdd(buff)+fucDel(buff)>0) return 1; // BAD: undefined behavior when calling functions to change the `buff` variable
...
intA = funcAdd(buff);
intB = funcDel(buff);
if(intA+intB>0) return 1; // GOOD: correct design

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>In some situations, the code constructs used may be executed in the wrong order in which the developer designed them. For example, if you call multiple functions as part of a single expression, and the functions have the ability to modify a shared resource, then the sequence in which the resource is changed can be unpredictable. These code snippets look suspicious and require the developer's attention.</p>
</overview>
<recommendation>
<p>We recommend that you use more guaranteed, in terms of sequence of execution, coding techniques.</p>
</recommendation>
<example>
<p>The following example demonstrates sections of code with insufficient execution sequence definition.</p>
<sample src="UndefinedOrImplementationDefinedBehavior.c" />
</example>
<references>
<li>
CWE Common Weakness Enumeration:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP10-C.+Do+not+depend+on+the+order+of+evaluation+of+subexpressions+or+the+order+in+which+side+effects+take+place"> EXP10-C. Do not depend on the order of evaluation of subexpressions or the order in which side effects take place</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,166 @@
/**
* @name Errors Of Undefined Program Behavior
* @description --In some situations, the code constructs used may be executed in the wrong order in which the developer designed them.
* --For example, if you call multiple functions as part of a single expression, and the functions have the ability to modify a shared resource, then the sequence in which the resource is changed can be unpredictable.
* --These code snippets look suspicious and require the developer's attention.
* @kind problem
* @id cpp/errors-of-undefined-program-behavior
* @problem.severity warning
* @precision medium
* @tags security
* external/cwe/cwe-758
*/
import cpp
import semmle.code.cpp.valuenumbering.HashCons
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* Threatening expressions of undefined behavior.
*/
class ExpressionsOfTheSameLevel extends Expr {
Expr exp2;
ExpressionsOfTheSameLevel() {
this != exp2 and
this.getParent() = exp2.getParent()
}
/** Holds if the underlying expression is a function call. */
predicate expressionCall() {
this instanceof FunctionCall and
exp2.getAChild*() instanceof FunctionCall and
not this.getParent() instanceof Operator and
not this.(FunctionCall).hasQualifier()
}
/** Holds if the underlying expression is a call to a function to free resources. */
predicate existsCloseOrFreeCall() {
(
globalValueNumber(this.(FunctionCall).getAnArgument()) =
globalValueNumber(exp2.getAChild*().(FunctionCall).getAnArgument()) or
hashCons(this.(FunctionCall).getAnArgument()) =
hashCons(exp2.getAChild*().(FunctionCall).getAnArgument())
) and
(
this.(FunctionCall).getTarget().hasGlobalOrStdName("close") or
this.(FunctionCall).getTarget().hasGlobalOrStdName("free") or
this.(FunctionCall).getTarget().hasGlobalOrStdName("fclose")
)
}
/** Holds if the arguments in the function can be changed. */
predicate generalArgumentDerivedType() {
exists(Parameter prt1, Parameter prt2, AssignExpr aet1, AssignExpr aet2, int i, int j |
not this.(FunctionCall).getArgument(i).isConstant() and
hashCons(this.(FunctionCall).getArgument(i)) =
hashCons(exp2.getAChild*().(FunctionCall).getArgument(j)) and
prt1 = this.(FunctionCall).getTarget().getParameter(i) and
prt2 = exp2.getAChild*().(FunctionCall).getTarget().getParameter(j) and
prt1.getType() instanceof DerivedType and
(
aet1 = this.(FunctionCall).getTarget().getEntryPoint().getASuccessor*() and
(
aet1.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() =
prt1.getAnAccess().getTarget() or
aet1.getLValue().(VariableAccess).getTarget() = prt1.getAnAccess().getTarget()
)
or
exists(FunctionCall fc1 |
fc1.getTarget().hasGlobalName("memcpy") and
fc1.getArgument(0).(VariableAccess).getTarget() = prt1.getAnAccess().getTarget() and
fc1 = this.(FunctionCall).getTarget().getEntryPoint().getASuccessor*()
)
) and
(
aet2 = exp2.getAChild*().(FunctionCall).getTarget().getEntryPoint().getASuccessor*() and
(
aet2.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() =
prt2.getAnAccess().getTarget() or
aet2.getLValue().(VariableAccess).getTarget() = prt2.getAnAccess().getTarget()
)
or
exists(FunctionCall fc1 |
fc1.getTarget().hasGlobalName("memcpy") and
fc1.getArgument(0).(VariableAccess).getTarget() = prt2.getAnAccess().getTarget() and
fc1 = exp2.(FunctionCall).getTarget().getEntryPoint().getASuccessor*()
)
)
)
}
/** Holds if functions have a common global argument. */
predicate generalGlobalArgument() {
exists(Declaration dl, AssignExpr aet1, AssignExpr aet2 |
dl instanceof GlobalVariable and
(
(
aet1.getLValue().(Access).getTarget() = dl or
aet1.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = dl
) and
aet1 = this.(FunctionCall).getTarget().getEntryPoint().getASuccessor*() and
not aet1.getRValue().isConstant()
or
exists(FunctionCall fc1 |
fc1.getTarget().hasGlobalName("memcpy") and
fc1.getArgument(0).(VariableAccess).getTarget() = dl and
fc1 = this.(FunctionCall).getTarget().getEntryPoint().getASuccessor*()
)
) and
(
(
aet2.getLValue().(Access).getTarget() = dl or
aet2.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = dl
) and
aet2 = exp2.(FunctionCall).getTarget().getEntryPoint().getASuccessor*()
or
exists(FunctionCall fc1 |
fc1.getTarget().hasGlobalName("memcpy") and
fc1.getArgument(0).(VariableAccess).getTarget() = dl and
fc1 = exp2.(FunctionCall).getTarget().getEntryPoint().getASuccessor*()
)
)
)
}
/** Holds if sequence point is not present in expression. */
predicate orderOfActionExpressions() {
not this.getParent() instanceof BinaryLogicalOperation and
not this.getParent() instanceof ConditionalExpr and
not this.getParent() instanceof Loop and
not this.getParent() instanceof CommaExpr
}
/** Holds if expression is crement. */
predicate dangerousCrementChanges() {
hashCons(this.(CrementOperation).getOperand()) = hashCons(exp2.(CrementOperation).getOperand())
or
hashCons(this.(CrementOperation).getOperand()) = hashCons(exp2)
or
hashCons(this.(CrementOperation).getOperand()) = hashCons(exp2.(ArrayExpr).getArrayOffset())
or
hashCons(this.(Assignment).getLValue()) = hashCons(exp2.(Assignment).getLValue())
or
not this.getAChild*() instanceof Call and
(
hashCons(this.getAChild*().(CrementOperation).getOperand()) = hashCons(exp2) or
hashCons(this.getAChild*().(CrementOperation).getOperand()) =
hashCons(exp2.(Assignment).getLValue())
)
}
}
from ExpressionsOfTheSameLevel eots
where
eots.orderOfActionExpressions() and
(
eots.expressionCall() and
(
eots.generalArgumentDerivedType() or
eots.generalGlobalArgument() or
eots.existsCloseOrFreeCall()
)
or
eots.dangerousCrementChanges()
)
select eots, "This expression may have undefined behavior."

View File

@@ -272,20 +272,16 @@ class File extends Container, @file {
* are compiled by a Microsoft compiler are detected by this predicate.
*/
predicate compiledAsMicrosoft() {
exists(Compilation c |
c.getAFileCompiled() = this and
exists(File f, Compilation c |
c.getAFileCompiled() = f and
(
c.getAnArgument() = "--microsoft" or
c.getAnArgument()
.toLowerCase()
.replaceAll("\\", "/")
.matches(["%/cl.exe", "%/clang-cl.exe"])
)
)
or
exists(File parent |
parent.compiledAsMicrosoft() and
parent.getAnIncludedFile() = this
) and
f.getAnIncludedFile*() = this
)
}
@@ -358,6 +354,11 @@ class File extends Container, @file {
string getShortName() { files(underlyingElement(this), _, result, _, _) }
}
/**
* Holds if any file was compiled by a Microsoft compiler.
*/
predicate anyFileCompiledAsMicrosoft() { any(File f).compiledAsMicrosoft() }
/**
* A C/C++ header file, as determined (mainly) by file extension.
*

View File

@@ -306,7 +306,7 @@ class FormatLiteral extends Literal {
* Holds if this `FormatLiteral` is in a context that supports
* Microsoft rules and extensions.
*/
predicate isMicrosoft() { any(File f).compiledAsMicrosoft() }
predicate isMicrosoft() { anyFileCompiledAsMicrosoft() }
/**
* Gets the format string, with '%%' and '%@' replaced by '_' (to avoid processing
@@ -869,6 +869,33 @@ class FormatLiteral extends Literal {
)
}
/**
* Gets an alternate argument type that would be required by the nth
* conversion specifier on a Microsoft or non-Microsoft platform, opposite
* to that of the snapshot. This may be useful for answering 'what might
* happen' questions.
*/
Type getConversionTypeAlternate(int n) {
exists(string len, string conv |
this.parseConvSpec(n, _, _, _, _, _, len, conv) and
(len != "l" and len != "w" and len != "h") and
getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function
(
conv = "c" and
result = getNonDefaultCharType()
or
conv = "C" and
result = getDefaultCharType()
or
conv = "s" and
result.(PointerType).getBaseType() = getNonDefaultCharType()
or
conv = "S" and
result.(PointerType).getBaseType() = getDefaultCharType()
)
)
}
/**
* Holds if the nth conversion specifier of this format string (if `mode = 2`), it's
* minimum field width (if `mode = 0`) or it's precision (if `mode = 1`) requires a

View File

@@ -208,7 +208,7 @@ private predicate bbSuccessorEntryReachesDefOrUse(
boolean skipsFirstLoopAlwaysTrueUponEntry
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
bbSuccessorEntryReachesLoopInvariant0(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
bbEntryReachesDefOrUseLocally(succ, v, defOrUse) and

View File

@@ -3,7 +3,250 @@
* reachability involving stack variables.
*/
import cpp
private import semmle.code.cpp.controlflow.Guards
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/** A `GuardCondition` which appear in a control-flow path to a sink. */
abstract private class LogicalGuardCondition extends GuardCondition {
LogicalGuardCondition() {
// Either the `GuardCondition` is part of the path from a source to a sink
revBbSuccessorEntryReaches0(_, this.getBasicBlock(), _, _, _)
or
// or it controls the basic block that contains the source node.
this.controls(any(BasicBlock bb | fwdBbEntryReachesLocally(bb, _, _, _)), _)
}
/**
* Holds if the truth of this logical expression having value `wholeIsTrue`
* implies that the truth of the child expression `part` has truth value `partIsTrue`.
*/
abstract predicate impliesCondition(
LogicalGuardCondition e, boolean testIsTrue, boolean condIsTrue
);
}
private class BinaryLogicalGuardCondition extends LogicalGuardCondition, BinaryLogicalOperation {
override predicate impliesCondition(
LogicalGuardCondition e, boolean testIsTrue, boolean condIsTrue
) {
this.impliesValue(e, testIsTrue, condIsTrue)
}
}
private class VariableGuardCondition extends LogicalGuardCondition, VariableAccess {
override predicate impliesCondition(
LogicalGuardCondition e, boolean testIsTrue, boolean condIsTrue
) {
this = e and
(
testIsTrue = true and condIsTrue = true
or
testIsTrue = false and condIsTrue = false
)
}
}
private class NotGuardCondition extends LogicalGuardCondition, NotExpr {
override predicate impliesCondition(
LogicalGuardCondition e, boolean testIsTrue, boolean condIsTrue
) {
e = this.getOperand() and
(
testIsTrue = true and
condIsTrue = false
or
testIsTrue = false and
condIsTrue = true
)
}
}
private newtype TCondition =
MkCondition(LogicalGuardCondition guard, boolean testIsTrue) { testIsTrue = [false, true] }
private class Condition extends MkCondition {
boolean testIsTrue;
LogicalGuardCondition guard;
Condition() { this = MkCondition(guard, testIsTrue) }
/**
* Holds if this condition having the value `this.getTruthValue()` implies that `cond` has truth
* value `cond.getTruthValue()`.
*/
string toString() { result = guard.toString() + " == " + testIsTrue.toString() }
/** Gets the value of this `Condition`. */
boolean getTruthValue() { result = testIsTrue }
LogicalGuardCondition getCondition() { result = guard }
pragma[nomagic]
predicate impliesCondition(Condition cond) {
exists(LogicalGuardCondition other |
other = cond.getCondition() and
this.getCondition()
.impliesCondition(globalValueNumber(other).getAnExpr(),
pragma[only_bind_into](pragma[only_bind_out](testIsTrue)),
pragma[only_bind_into](pragma[only_bind_out](cond.getTruthValue())))
)
}
/** Gets the negated expression represented by this `Condition`, if any. */
private Condition negate() {
result.getCondition() = guard and
result.getTruthValue() = testIsTrue.booleanNot()
}
/**
* Holds if this condition having the value `this.getTruthValue()` implies that `cond` cannot have
* the truth value `cond.getTruthValue()`.
*/
final predicate refutesCondition(Condition cond) { this.impliesCondition(cond.negate()) }
/** Gets the `Location` of the expression that generated this `Condition`. */
Location getLocation() { result = guard.getLocation() }
}
/**
* Gets a `Condition` that controls `b`. That is, to enter `b` the condition must hold.
*/
private Condition getADirectCondition(BasicBlock b) {
result.getCondition().controls(b, result.getTruthValue())
}
/**
* Like the shared dataflow library, the reachability analysis is split into two stages:
* In the first stage, we compute an overapproximation of the possible control-flow paths where we don't
* reason about path conditions. This stage is split into phases: A forward phase (computed by the
* predicates prefixes with `fwd`), and a reverse phase (computed by the predicates prefixed with `rev`).
*
* The forward phease computes the set of control-flow nodes reachable from a given `source` and `v` such
* that `config.isSource(source, v)` holds.
*
* See the QLDoc on `revBbSuccessorEntryReaches0` for a description of what the reverse phase computes.
*/
private predicate fwdBbSuccessorEntryReaches0(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v,
boolean skipsFirstLoopAlwaysTrueUponEntry, StackVariableReachability config
) {
fwdBbEntryReachesLocally(bb, v, source, config) and
skipsFirstLoopAlwaysTrueUponEntry = false
or
exists(BasicBlock pred, boolean predSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant0(pred, bb, predSkipsFirstLoopAlwaysTrueUponEntry,
skipsFirstLoopAlwaysTrueUponEntry)
|
// Note we cannot filter out barriers at this point.
// See the comment in `revBbSuccessorEntryReaches0` for an explanation why,
fwdBbSuccessorEntryReaches0(source, pred, v, predSkipsFirstLoopAlwaysTrueUponEntry, config)
)
}
/**
* The second phase of the first stages computes, for each `source` and `v` pair such
* that `config.isSource(source, v)`, which sinks are reachable from that `(source, v)` pair.
*/
private predicate revBbSuccessorEntryReaches0(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v,
boolean skipsFirstLoopAlwaysTrueUponEntry, StackVariableReachability config
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
fwdBbSuccessorEntryReaches0(source, bb, v, skipsFirstLoopAlwaysTrueUponEntry, config) and
bbSuccessorEntryReachesLoopInvariant0(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
revBbEntryReachesLocally(succ, v, _, config) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
// Note: We cannot rule out a successor block that contain a barrier here (like we do later in
// `bbSuccessorEntryReaches`) as we might later discover that the only way to get through a piece of
// code is through that barrier, and we want to discover this in
// `bbSuccessorEntryReachesLoopInvariant`. As an example, consider this piece of code:
// ```
// if(b) { (1) source(); }
// (2) if(b) { (3) barrier(); }
// (4) sink();
// ```
// here, we want the successor relation to contain:
// 1 -> {2}, 2 -> {3, 4}
// since the second stage will deduce that the edge (2) -> (3) is unconditional (as b is always true
// if we start at `source()`), and so there is actually no path from (1) to (4) without going through
// a barrier.
revBbSuccessorEntryReaches0(source, succ, v, succSkipsFirstLoopAlwaysTrueUponEntry, config)
)
}
private predicate successorExitsLoop(BasicBlock pred, BasicBlock succ, Loop loop) {
pred.getASuccessor() = succ and
bbDominates(loop.getStmt(), pred) and
not bbDominates(loop.getStmt(), succ)
}
private predicate successorExitsFirstDisjunct(BasicBlock pred, BasicBlock succ) {
exists(LogicalOrExpr orExpr | orExpr instanceof GuardCondition |
pred.getAFalseSuccessor() = succ and
pred.contains(orExpr.getLeftOperand())
)
}
/**
* When we exit a loop, we filter out the conditions that arise from the loop's guard.
* To see why this is necessary, consider this example:
* ```
* (1) source();
* while (b) { (2) ... }
* (3) sink();
* ```
* If we keep all the conditions when we transition from (2) to (3) we learn that `b` is true at
* (3), but since we exited the loop we also learn that `b` is false at 3.
* Thus, when we transition from (2) to (3) we discard all those conditions that are true at (2),
* but NOT true at (3).
*/
private predicate isLoopCondition(LogicalGuardCondition cond, BasicBlock pred, BasicBlock bb) {
exists(Loop loop, boolean testIsTrue | successorExitsLoop(pred, bb, loop) |
// the resulting `Condition` holds inside the loop
cond.controls(pred, testIsTrue) and
// but not prior to the loop.
not cond.controls(loop.getBasicBlock(), testIsTrue)
)
}
/**
* When we leave the first disjunct we throw away the condition that says the the first disjunct is
* false. To see why this is necessary, consider this example:
* ```
* if((1) b1 || (2) b2) { (3) ... }
* ```
* it holds that `b1 == false` controls (2), and since (2) steps to (3) we learn that `b1 == false `
* holds at (3). So we filter out the conditions that we learn from leaving taking the false
* branch in a disjunction.
*/
private predicate isDisjunctionCondition(LogicalGuardCondition cond, BasicBlock pred, BasicBlock bb) {
exists(boolean testIsTrue | successorExitsFirstDisjunct(pred, bb) |
// the resulting `Condition` holds after evaluating the left-hand side
cond.controls(bb, testIsTrue) and
// but not before evaluating the left-hand side.
not cond.controls(pred, testIsTrue)
)
}
private predicate isLoopVariantCondition(LogicalGuardCondition cond, BasicBlock pred, BasicBlock bb) {
exists(Loop loop |
bb.getEnd() = loop.getCondition() and
pred.getASuccessor() = bb and
bbDominates(bb, pred) and
loopVariant(cond.getAChild*(), loop)
)
}
private predicate loopVariant(VariableAccess e, Loop loop) {
exists(SsaDefinition d | d.getAUse(e.getTarget()) = e |
d.getAnUltimateDefiningValue(e.getTarget()) = loop.getCondition().getAChild*() or
d.getAnUltimateDefiningValue(e.getTarget()).getEnclosingStmt().getParent*() = loop.getStmt() or
d.getAnUltimateDefiningValue(e.getTarget()) = loop.(ForStmt).getUpdate().getAChild*()
)
}
/**
* A reachability analysis for control-flow nodes involving stack variables.
@@ -60,7 +303,8 @@ abstract class StackVariableReachability extends string {
* ```
*
* In addition to using a better performing implementation, this analysis
* accounts for loops where the condition is provably true upon entry.
* accounts for loops where the condition is provably true upon entry, and discards paths that require
* an infeasible combination of guard conditions (for example, `if(b) { ... }` and `if(!b) { ... }`).
*/
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
/*
@@ -80,46 +324,184 @@ abstract class StackVariableReachability extends string {
j > i and
sink = bb.getNode(j) and
isSink(sink, v) and
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
not isBarrier(bb.getNode(pragma[only_bind_into]([i + 1 .. j - 1])), v)
)
or
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
bbSuccessorEntryReaches(bb, v, sink, _)
bbSuccessorEntryReaches(source, bb, v, sink, _)
)
}
private Condition getASinkCondition(SemanticStackVariable v) {
exists(BasicBlock bb |
revBbEntryReachesLocally(bb, v, _, this) and
result.getCondition().controls(bb, result.getTruthValue())
)
}
private Condition getABarrierCondition(SemanticStackVariable v) {
exists(BasicBlock bb |
isBarrier(bb.getANode(), v) and
result.getCondition().controls(bb, result.getTruthValue())
)
}
/**
* Gets a condition with a known truth value in `bb` when the control-flow starts at the source
* node `source` and we're tracking reachability using variable `v` (that is,
* `this.isSource(source, v)` holds).
*
* This predicate is `pragma[noopt]` as it seems difficult to get the correct join order for the
* recursive case otherwise:
* revBbSuccessorEntryReaches0(bb) -> getASuccessor -> prev_delta ->
* revBbSuccessorEntryReaches0(pred) -> {isLoopCondition, isDisjunctionCondition, isLoopVariantCondition}
*/
pragma[noopt]
private Condition getACondition(ControlFlowNode source, SemanticStackVariable v, BasicBlock bb) {
revBbSuccessorEntryReaches0(source, bb, v, _, this) and
(
result = getADirectCondition(bb) and
(
exists(Condition c |
c = getASinkCondition(v) and
result.refutesCondition(c)
)
or
exists(Condition c |
c = getABarrierCondition(v) and
result.impliesCondition(c)
)
)
or
exists(BasicBlock pred |
pred.getASuccessor() = bb and
result = getACondition(source, v, pred) and
revBbSuccessorEntryReaches0(source, pred, v, _, this) and
exists(LogicalGuardCondition c | c = result.getCondition() |
not isLoopCondition(c, pred, bb) and
not isDisjunctionCondition(c, pred, bb) and
not isLoopVariantCondition(c, pred, bb)
)
)
)
}
pragma[nomagic]
private predicate bbSuccessorEntryReachesLoopInvariantSucc(
ControlFlowNode source, BasicBlock pred, SemanticStackVariable v, BasicBlock succ,
boolean predSkipsFirstLoopAlwaysTrueUponEntry
) {
revBbSuccessorEntryReaches0(source, pragma[only_bind_into](pred), v,
predSkipsFirstLoopAlwaysTrueUponEntry, this) and
pred.getASuccessor() = succ
}
pragma[nomagic]
private predicate bbSuccessorEntryReachesLoopInvariantCand(
ControlFlowNode source, BasicBlock pred, SemanticStackVariable v, BasicBlock succ,
boolean predSkipsFirstLoopAlwaysTrueUponEntry, boolean succSkipsFirstLoopAlwaysTrueUponEntry
) {
bbSuccessorEntryReachesLoopInvariantSucc(source, pragma[only_bind_into](pred), v, succ,
predSkipsFirstLoopAlwaysTrueUponEntry) and
bbSuccessorEntryReachesLoopInvariant0(pred, succ, predSkipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
}
/**
* Holds if `pred`, `succ`, `predSkipsFirstLoopAlwaysTrueUponEntry` and
* `succSkipsFirstLoopAlwaysTrueUponEntry` satisfy the loop invariants specified in the QLDoc
* for `bbSuccessorEntryReachesLoopInvariant0`.
*
* In addition, this predicate:
* 1. Rules out successor blocks that are unreachable due to contradictory path conditions.
* 2. Refines the successor relation when the edge `pred -> succ` is a conditional edge whose truth
* value is known.
*/
pragma[nomagic]
private predicate bbSuccessorEntryReachesLoopInvariant(
ControlFlowNode source, BasicBlock pred, SemanticStackVariable v, BasicBlock succ,
boolean predSkipsFirstLoopAlwaysTrueUponEntry, boolean succSkipsFirstLoopAlwaysTrueUponEntry
) {
bbSuccessorEntryReachesLoopInvariantCand(source, pred, v, succ,
predSkipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) and
not exists(Condition cond, Condition direct |
cond = getACondition(source, v, pred) and
direct = pragma[only_bind_out](getADirectCondition(succ)) and
cond.refutesCondition(direct)
) and
(
// If we picked the successor edge corresponding to a condition being true, there must not be
// another path condition that refutes that the condition is true.
not exists(Condition cond | cond = getACondition(source, v, pred) |
succ = pred.getATrueSuccessor() and
cond.refutesCondition(pragma[only_bind_out](MkCondition(pred.getEnd(), true)))
) and
// If we picked the successor edge corresponding to a condition being false, there must not be
// another path condition that refutes that the condition is false.
not exists(Condition cond | cond = getACondition(source, v, pred) |
succ = pred.getAFalseSuccessor() and
cond.refutesCondition(pragma[only_bind_out](MkCondition(pred.getEnd(), false)))
)
)
}
private predicate bbSuccessorEntryReaches(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
boolean skipsFirstLoopAlwaysTrueUponEntry
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
bbSuccessorEntryReachesLoopInvariant(source, bb, v, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
bbEntryReachesLocally(succ, v, node) and
revBbEntryReachesLocally(succ, v, node, this) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not isBarrier(succ.getNode(_), v) and
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
bbSuccessorEntryReachesLoopInvariant(source, bb, v, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and
not isBarrier(pragma[only_bind_out](succ.getANode()), v) and
pragma[only_bind_into](this)
.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
}
private predicate bbEntryReachesLocally(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) {
exists(int n |
node = bb.getNode(n) and
isSink(node, v)
|
not exists(this.firstBarrierIndexIn(bb, v))
private predicate fwdBbEntryReachesLocally(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node, StackVariableReachability config
) {
exists(int n |
node = bb.getNode(n) and
config.isSource(node, v) and
(
not exists(lastBarrierIndexIn(bb, v, config))
or
n <= this.firstBarrierIndexIn(bb, v)
lastBarrierIndexIn(bb, v, config) <= n
)
}
)
}
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
result = min(int m | isBarrier(bb.getNode(m), v))
}
private predicate revBbEntryReachesLocally(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node, StackVariableReachability config
) {
exists(int n |
node = bb.getNode(n) and
config.isSink(node, v)
|
not exists(firstBarrierIndexIn(bb, v, config))
or
n <= firstBarrierIndexIn(bb, v, config)
)
}
private int firstBarrierIndexIn(
BasicBlock bb, SemanticStackVariable v, StackVariableReachability config
) {
result = min(int m | config.isBarrier(bb.getNode(m), v))
}
private int lastBarrierIndexIn(
BasicBlock bb, SemanticStackVariable v, StackVariableReachability config
) {
result = max(int m | config.isBarrier(bb.getNode(m), v))
}
/**
@@ -182,7 +564,7 @@ private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(
* is provably true upon entry, then `succ` is not allowed to skip
* that loop (`succSkipsFirstLoopAlwaysTrueUponEntry = false`).
*/
predicate bbSuccessorEntryReachesLoopInvariant(
predicate bbSuccessorEntryReachesLoopInvariant0(
BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry,
boolean succSkipsFirstLoopAlwaysTrueUponEntry
) {
@@ -296,10 +678,52 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
)
}
private predicate bbSuccessorEntryReaches(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
boolean skipsFirstLoopAlwaysTrueUponEntry
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant0(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
revBbEntryReachesLocally(succ, v, node, this) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not isBarrier(succ.getNode(_), v) and
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
private predicate reaches0(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
/*
* Implementation detail: the predicates in this class are a generalization of
* those in DefinitionsAndUses.qll, and should be kept in sync.
*
* Unfortunately, caching of abstract predicates does not work well, so the
* predicates in DefinitionsAndUses.qll cannot use this library.
*/
exists(BasicBlock bb, int i |
isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
isSink(sink, v) and
not isBarrier(bb.getNode(pragma[only_bind_into]([i + 1 .. j - 1])), v)
)
or
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
bbSuccessorEntryReaches(bb, v, sink, _)
)
}
private predicate reassignment(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) {
StackVariableReachability.super.reaches(source, v, def) and
reaches0(source, v, def) and
exprDefinition(v0, def, v.getAnAccess())
}
@@ -365,11 +789,11 @@ abstract class StackVariableReachabilityExt extends string {
boolean skipsFirstLoopAlwaysTrueUponEntry
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
bbSuccessorEntryReachesLoopInvariant0(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and
not isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
bbEntryReachesLocally(source, succ, v, node) and
this.bbEntryReachesLocally(source, succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -1117,6 +1117,44 @@ ReturnPosition getReturnPosition(ReturnNodeExt ret) {
result = getReturnPosition0(ret, ret.getKind())
}
/**
* Checks whether `inner` can return to `call` in the call context `innercc`.
* Assumes a context of `inner = viableCallableExt(call)`.
*/
bindingset[innercc, inner, call]
predicate checkCallContextReturn(CallContext innercc, DataFlowCallable inner, DataFlowCall call) {
innercc instanceof CallContextAny
or
exists(DataFlowCallable c0, DataFlowCall call0 |
callEnclosingCallable(call0, inner) and
innercc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
}
/**
* Checks whether `call` can resolve to `calltarget` in the call context `cc`.
* Assumes a context of `calltarget = viableCallableExt(call)`.
*/
bindingset[cc, call, calltarget]
predicate checkCallContextCall(CallContext cc, DataFlowCall call, DataFlowCallable calltarget) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
if reducedViableImplInCallContext(call, _, ctx)
then calltarget = prunedViableImplInCallContext(call, ctx)
else any()
)
or
cc instanceof CallContextSomeCall
or
cc instanceof CallContextAny
or
cc instanceof CallContextReturn
}
/**
* Resolves a return from `callable` in `cc` to `call`. This is equivalent to
* `callable = viableCallableExt(call) and checkCallContextReturn(cc, callable, call)`.
*/
bindingset[cc, callable]
predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) {
cc instanceof CallContextAny and callable = viableCallableExt(call)
@@ -1128,6 +1166,10 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
)
}
/**
* Resolves a call from `call` in `cc` to `result`. This is equivalent to
* `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`.
*/
bindingset[call, cc]
DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -1117,6 +1117,44 @@ ReturnPosition getReturnPosition(ReturnNodeExt ret) {
result = getReturnPosition0(ret, ret.getKind())
}
/**
* Checks whether `inner` can return to `call` in the call context `innercc`.
* Assumes a context of `inner = viableCallableExt(call)`.
*/
bindingset[innercc, inner, call]
predicate checkCallContextReturn(CallContext innercc, DataFlowCallable inner, DataFlowCall call) {
innercc instanceof CallContextAny
or
exists(DataFlowCallable c0, DataFlowCall call0 |
callEnclosingCallable(call0, inner) and
innercc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
}
/**
* Checks whether `call` can resolve to `calltarget` in the call context `cc`.
* Assumes a context of `calltarget = viableCallableExt(call)`.
*/
bindingset[cc, call, calltarget]
predicate checkCallContextCall(CallContext cc, DataFlowCall call, DataFlowCallable calltarget) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
if reducedViableImplInCallContext(call, _, ctx)
then calltarget = prunedViableImplInCallContext(call, ctx)
else any()
)
or
cc instanceof CallContextSomeCall
or
cc instanceof CallContextAny
or
cc instanceof CallContextReturn
}
/**
* Resolves a return from `callable` in `cc` to `call`. This is equivalent to
* `callable = viableCallableExt(call) and checkCallContextReturn(cc, callable, call)`.
*/
bindingset[cc, callable]
predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) {
cc instanceof CallContextAny and callable = viableCallableExt(call)
@@ -1128,6 +1166,10 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
)
}
/**
* Resolves a call from `call` in `cc` to `result`. This is equivalent to
* `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`.
*/
bindingset[call, cc]
DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |

View File

@@ -50,7 +50,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
* Holds if this `FormattingFunction` is in a context that supports
* Microsoft rules and extensions.
*/
predicate isMicrosoft() { any(File f).compiledAsMicrosoft() }
predicate isMicrosoft() { anyFileCompiledAsMicrosoft() }
/**
* Holds if the default meaning of `%s` is a `wchar_t *`, rather than

View File

@@ -0,0 +1,3 @@
| test.c:13:10:13:21 | call to tmpFunction1 | This expression may have undefined behavior. |
| test.c:13:30:13:41 | call to tmpFunction2 | This expression may have undefined behavior. |
| test.c:16:15:16:20 | ... ++ | This expression may have undefined behavior. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql

View File

@@ -0,0 +1,19 @@
char tmpFunction1(char * buf)
{
buf[1]=buf[1] + buf[2] + buf[3];
return buf[1];
}
char tmpFunction2(char * buf)
{
buf[2]=buf[1] + buf[2] + buf[3];
return buf[2];
}
void workFunction_0(char *s, char * buf) {
int intA;
intA = tmpFunction1(buf) + tmpFunction2(buf); // BAD
intA = tmpFunction1(buf); //GOOD
intA += tmpFunction2(buf); // GOOD
buf[intA] = intA++; // BAD
intA++;
buf[intA] = intA; // GOOD
}

View File

@@ -1,13 +1,21 @@
| fields.cpp:3:8:3:12 | Entry | fields.cpp:4:9:4:12 | name | public | CharPointerType | char |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:4:9:4:12 | name | public | PointerDumpType | char |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:5:8:5:8 | t | public | Enum | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:5:8:5:8 | t | public | UserDumpType | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:6:9:6:9 | s | public | CharPointerType | char |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:6:9:6:9 | s | public | PointerDumpType | char |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:7:7:7:7 | i | public | IntType | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:7:7:7:7 | i | public | IntegralDumpType | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:7:7:7:7 | i | public | MicrosoftInt32Type | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:9:7:9:14 | internal | private | IntType | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:9:7:9:14 | internal | private | IntegralDumpType | |
| fields.cpp:3:8:3:12 | Entry | fields.cpp:9:7:9:14 | internal | private | MicrosoftInt32Type | |
| fields.cpp:12:7:12:10 | Name | fields.cpp:13:15:13:15 | s | private | PointerType | const char |
| fields.cpp:16:7:16:11 | Table | fields.cpp:17:9:17:9 | p | private | PointerType | Name |
| fields.cpp:12:7:12:10 | Name | fields.cpp:13:15:13:15 | s | private | PointerDumpType | const char |
| fields.cpp:16:7:16:11 | Table | fields.cpp:17:9:17:9 | p | private | PointerDumpType | Name |
| fields.cpp:16:7:16:11 | Table | fields.cpp:18:7:18:8 | sz | private | IntType | |
| fields.cpp:16:7:16:11 | Table | fields.cpp:18:7:18:8 | sz | private | IntegralDumpType | |
| fields.cpp:16:7:16:11 | Table | fields.cpp:18:7:18:8 | sz | private | MicrosoftInt32Type | |
| fields.cpp:26:7:26:10 | Date | fields.cpp:28:16:28:26 | cache_valid | private | BoolType | |
| fields.cpp:26:7:26:10 | Date | fields.cpp:28:16:28:26 | cache_valid | private | IntegralDumpType | |
| fields.cpp:26:7:26:10 | Date | fields.cpp:30:17:30:21 | cache | public | CharPointerType | char |
| fields.cpp:26:7:26:10 | Date | fields.cpp:30:17:30:21 | cache | public | PointerDumpType | char |

View File

@@ -1 +1 @@
| routinetype.cpp:2:7:2:19 | myRoutineType | file://:0:0:0:0 | ..()(..) | RoutineType |
| routinetype.cpp:2:7:2:19 | myRoutineType | file://:0:0:0:0 | ..()(..) | PrintableElement, RoutineDumpType |

View File

@@ -1,2 +1,2 @@
| typedefs.cpp:6:6:6:7 | f1 | typedefs.cpp:8:15:8:18 | TYPE | CTypedefType, LocalTypedefType |
| typedefs.cpp:6:6:6:7 | f1 | typedefs.cpp:9:9:9:9 | D | DirectAccessHolder, LocalClass, MetricClass, StructLikeClass |
| typedefs.cpp:6:6:6:7 | f1 | typedefs.cpp:8:15:8:18 | TYPE | CTypedefType, LocalTypedefType, PrintableElement, UserDumpType |
| typedefs.cpp:6:6:6:7 | f1 | typedefs.cpp:9:9:9:9 | D | DirectAccessHolder, LocalClass, MetricClass, PrintableElement, StructLikeClass, UserDumpType |

View File

@@ -1,3 +1,3 @@
| file://:0:0:0:0 | __wchar_t * | PointerType | Wchar_t, WideCharType |
| file://:0:0:0:0 | const __wchar_t | SpecifiedType | Wchar_t, WideCharType |
| file://:0:0:0:0 | wchar_t | Wchar_t, WideCharType | |
| file://:0:0:0:0 | __wchar_t * | PointerDumpType, PrintableElement | IntegralDumpType, PrintableElement, Wchar_t, WideCharType |
| file://:0:0:0:0 | const __wchar_t | PrintableElement, SpecifiedDumpType | IntegralDumpType, PrintableElement, Wchar_t, WideCharType |
| file://:0:0:0:0 | wchar_t | IntegralDumpType, PrintableElement, Wchar_t, WideCharType | |

View File

@@ -1,8 +1,8 @@
| cstd_types.cpp:47:13:47:15 | if8 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast8_t |
| cstd_types.cpp:48:14:48:17 | if16 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast16_t |
| cstd_types.cpp:49:14:49:17 | if32 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast32_t |
| cstd_types.cpp:50:14:50:17 | if64 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast64_t |
| cstd_types.cpp:51:14:51:16 | uf8 | CTypedefType, FastestMinimumWidthIntegralType, UInt_fast8_t |
| cstd_types.cpp:52:15:52:18 | uf16 | CTypedefType, FastestMinimumWidthIntegralType, UInt_fast16_t |
| cstd_types.cpp:53:15:53:18 | uf32 | CTypedefType, FastestMinimumWidthIntegralType, UInt_fast32_t |
| cstd_types.cpp:54:15:54:18 | uf64 | CTypedefType, FastestMinimumWidthIntegralType, UInt_fast64_t |
| cstd_types.cpp:47:13:47:15 | if8 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast8_t, PrintableElement, UserDumpType |
| cstd_types.cpp:48:14:48:17 | if16 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast16_t, PrintableElement, UserDumpType |
| cstd_types.cpp:49:14:49:17 | if32 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast32_t, PrintableElement, UserDumpType |
| cstd_types.cpp:50:14:50:17 | if64 | CTypedefType, FastestMinimumWidthIntegralType, Int_fast64_t, PrintableElement, UserDumpType |
| cstd_types.cpp:51:14:51:16 | uf8 | CTypedefType, FastestMinimumWidthIntegralType, PrintableElement, UInt_fast8_t, UserDumpType |
| cstd_types.cpp:52:15:52:18 | uf16 | CTypedefType, FastestMinimumWidthIntegralType, PrintableElement, UInt_fast16_t, UserDumpType |
| cstd_types.cpp:53:15:53:18 | uf32 | CTypedefType, FastestMinimumWidthIntegralType, PrintableElement, UInt_fast32_t, UserDumpType |
| cstd_types.cpp:54:15:54:18 | uf64 | CTypedefType, FastestMinimumWidthIntegralType, PrintableElement, UInt_fast64_t, UserDumpType |

View File

@@ -1,8 +1,8 @@
| cstd_types.cpp:31:8:31:9 | i8 | CTypedefType, FixedWidthIntegralType, Int8_t |
| cstd_types.cpp:32:9:32:11 | i16 | CTypedefType, FixedWidthIntegralType, Int16_t |
| cstd_types.cpp:33:9:33:11 | i32 | CTypedefType, FixedWidthIntegralType, Int32_t |
| cstd_types.cpp:34:9:34:11 | i64 | CTypedefType, FixedWidthIntegralType, Int64_t |
| cstd_types.cpp:35:9:35:11 | ui8 | CTypedefType, FixedWidthIntegralType, UInt8_t |
| cstd_types.cpp:36:10:36:13 | ui16 | CTypedefType, FixedWidthIntegralType, UInt16_t |
| cstd_types.cpp:37:10:37:13 | ui32 | CTypedefType, FixedWidthIntegralType, UInt32_t |
| cstd_types.cpp:38:10:38:13 | ui64 | CTypedefType, FixedWidthIntegralType, UInt64_t |
| cstd_types.cpp:31:8:31:9 | i8 | CTypedefType, FixedWidthIntegralType, Int8_t, PrintableElement, UserDumpType |
| cstd_types.cpp:32:9:32:11 | i16 | CTypedefType, FixedWidthIntegralType, Int16_t, PrintableElement, UserDumpType |
| cstd_types.cpp:33:9:33:11 | i32 | CTypedefType, FixedWidthIntegralType, Int32_t, PrintableElement, UserDumpType |
| cstd_types.cpp:34:9:34:11 | i64 | CTypedefType, FixedWidthIntegralType, Int64_t, PrintableElement, UserDumpType |
| cstd_types.cpp:35:9:35:11 | ui8 | CTypedefType, FixedWidthIntegralType, PrintableElement, UInt8_t, UserDumpType |
| cstd_types.cpp:36:10:36:13 | ui16 | CTypedefType, FixedWidthIntegralType, PrintableElement, UInt16_t, UserDumpType |
| cstd_types.cpp:37:10:37:13 | ui32 | CTypedefType, FixedWidthIntegralType, PrintableElement, UInt32_t, UserDumpType |
| cstd_types.cpp:38:10:38:13 | ui64 | CTypedefType, FixedWidthIntegralType, PrintableElement, UInt64_t, UserDumpType |

View File

@@ -1,2 +1,2 @@
| cstd_types.cpp:74:4:74:6 | _e0 | Enum, FixedWidthEnumType |
| cstd_types.cpp:75:4:75:6 | _e1 | FixedWidthEnumType, ScopedEnum |
| cstd_types.cpp:74:4:74:6 | _e0 | Enum, FixedWidthEnumType, PrintableElement, UserDumpType |
| cstd_types.cpp:75:4:75:6 | _e1 | FixedWidthEnumType, PrintableElement, ScopedEnum, UserDumpType |

View File

@@ -1,2 +1,2 @@
| cstd_types.cpp:55:10:55:11 | im | CTypedefType, Intmax_t, MaximumWidthIntegralType |
| cstd_types.cpp:56:11:56:13 | uim | CTypedefType, MaximumWidthIntegralType, Uintmax_t |
| cstd_types.cpp:55:10:55:11 | im | CTypedefType, Intmax_t, MaximumWidthIntegralType, PrintableElement, UserDumpType |
| cstd_types.cpp:56:11:56:13 | uim | CTypedefType, MaximumWidthIntegralType, PrintableElement, Uintmax_t, UserDumpType |

View File

@@ -1,8 +1,8 @@
| cstd_types.cpp:39:15:39:16 | l8 | CTypedefType, Int_least8_t, MinimumWidthIntegralType |
| cstd_types.cpp:40:15:40:17 | l16 | CTypedefType, Int_least16_t, MinimumWidthIntegralType |
| cstd_types.cpp:41:15:41:17 | l32 | CTypedefType, Int_least32_t, MinimumWidthIntegralType |
| cstd_types.cpp:42:15:42:17 | l64 | CTypedefType, Int_least64_t, MinimumWidthIntegralType |
| cstd_types.cpp:43:15:43:17 | ul8 | CTypedefType, MinimumWidthIntegralType, UInt_least8_t |
| cstd_types.cpp:44:16:44:19 | ul16 | CTypedefType, MinimumWidthIntegralType, UInt_least16_t |
| cstd_types.cpp:45:16:45:19 | ul32 | CTypedefType, MinimumWidthIntegralType, UInt_least32_t |
| cstd_types.cpp:46:16:46:19 | ul64 | CTypedefType, MinimumWidthIntegralType, UInt_least64_t |
| cstd_types.cpp:39:15:39:16 | l8 | CTypedefType, Int_least8_t, MinimumWidthIntegralType, PrintableElement, UserDumpType |
| cstd_types.cpp:40:15:40:17 | l16 | CTypedefType, Int_least16_t, MinimumWidthIntegralType, PrintableElement, UserDumpType |
| cstd_types.cpp:41:15:41:17 | l32 | CTypedefType, Int_least32_t, MinimumWidthIntegralType, PrintableElement, UserDumpType |
| cstd_types.cpp:42:15:42:17 | l64 | CTypedefType, Int_least64_t, MinimumWidthIntegralType, PrintableElement, UserDumpType |
| cstd_types.cpp:43:15:43:17 | ul8 | CTypedefType, MinimumWidthIntegralType, PrintableElement, UInt_least8_t, UserDumpType |
| cstd_types.cpp:44:16:44:19 | ul16 | CTypedefType, MinimumWidthIntegralType, PrintableElement, UInt_least16_t, UserDumpType |
| cstd_types.cpp:45:16:45:19 | ul32 | CTypedefType, MinimumWidthIntegralType, PrintableElement, UInt_least32_t, UserDumpType |
| cstd_types.cpp:46:16:46:19 | ul64 | CTypedefType, MinimumWidthIntegralType, PrintableElement, UInt_least64_t, UserDumpType |

View File

@@ -1,4 +1,4 @@
| integral_types.cpp:2:8:2:9 | i8 | file://:0:0:0:0 | char | MicrosoftInt8Type, PlainCharType |
| integral_types.cpp:3:9:3:11 | i16 | file://:0:0:0:0 | short | MicrosoftInt16Type, ShortType |
| integral_types.cpp:4:9:4:11 | i32 | file://:0:0:0:0 | int | IntType, MicrosoftInt32Type |
| integral_types.cpp:5:9:5:11 | i64 | file://:0:0:0:0 | long long | LongLongType, MicrosoftInt64Type |
| integral_types.cpp:2:8:2:9 | i8 | file://:0:0:0:0 | char | IntegralDumpType, MicrosoftInt8Type, PlainCharType, PrintableElement |
| integral_types.cpp:3:9:3:11 | i16 | file://:0:0:0:0 | short | IntegralDumpType, MicrosoftInt16Type, PrintableElement, ShortType |
| integral_types.cpp:4:9:4:11 | i32 | file://:0:0:0:0 | int | IntType, IntegralDumpType, MicrosoftInt32Type, PrintableElement |
| integral_types.cpp:5:9:5:11 | i64 | file://:0:0:0:0 | long long | IntegralDumpType, LongLongType, MicrosoftInt64Type, PrintableElement |

View File

@@ -1,3 +1,3 @@
| file://:0:0:0:0 | wchar_t | Wchar_t, WideCharType | |
| file://:0:0:0:0 | wchar_t * | PointerType | CTypedefType, Wchar_t |
| ms.c:2:24:2:30 | wchar_t | CTypedefType, Wchar_t | |
| file://:0:0:0:0 | wchar_t | IntegralDumpType, PrintableElement, Wchar_t, WideCharType | |
| file://:0:0:0:0 | wchar_t * | PointerDumpType, PrintableElement | CTypedefType, PrintableElement, UserDumpType, Wchar_t |
| ms.c:2:24:2:30 | wchar_t | CTypedefType, PrintableElement, UserDumpType, Wchar_t | |

View File

@@ -1,94 +1,94 @@
| ..()(..) | RoutineType | | | | |
| ..(*)(..) | FunctionPointerType | | ..()(..) | | |
| _Complex __float128 | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex double | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex float | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex long double | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Decimal32 | Decimal32Type | | | | |
| _Decimal64 | Decimal64Type | | | | |
| _Decimal128 | Decimal128Type | | | | |
| _Float32 | BinaryFloatingPointType, RealNumberType | | | | |
| _Float32x | BinaryFloatingPointType, RealNumberType | | | | |
| _Float64 | BinaryFloatingPointType, RealNumberType | | | | |
| _Float64x | BinaryFloatingPointType, RealNumberType | | | | |
| _Float128 | BinaryFloatingPointType, RealNumberType | | | | |
| _Float128x | BinaryFloatingPointType, RealNumberType | | | | |
| _Imaginary double | BinaryFloatingPointType, ImaginaryNumberType | | | | |
| _Imaginary float | BinaryFloatingPointType, ImaginaryNumberType | | | | |
| _Imaginary long double | BinaryFloatingPointType, ImaginaryNumberType | | | | |
| __float128 | Float128Type | | | | |
| __int128 | Int128Type | | | | |
| __va_list_tag | DirectAccessHolder, MetricClass, Struct, StructLikeClass | | | | |
| __va_list_tag & | LValueReferenceType | | __va_list_tag | | |
| __va_list_tag && | RValueReferenceType | | __va_list_tag | | |
| address | DirectAccessHolder, MetricClass, Struct, StructLikeClass | | | | |
| address & | LValueReferenceType | | address | | |
| address && | RValueReferenceType | | address | | |
| auto | AutoType | | | | |
| bool | BoolType | | | | |
| char | MicrosoftInt8Type, PlainCharType | | | | |
| char8_t | Char8Type | | | | |
| char16_t | Char16Type | | | | |
| char32_t | Char32Type | | | | |
| char * | CharPointerType | | char | | |
| char *[3] | ArrayType | char * | char * | | |
| char *[32] | ArrayType | char * | char * | | |
| char *[] | ArrayType | char * | char * | | |
| char[2] | ArrayType | char | char | | |
| char[3] | ArrayType | char | char | | |
| char[5] | ArrayType | char | char | | |
| char[6] | ArrayType | char | char | | |
| char[8] | ArrayType | char | char | | |
| char[9] | ArrayType | char | char | | |
| char[10] | ArrayType | char | char | | |
| char[53] | ArrayType | char | char | | |
| char[] | ArrayType | char | char | | |
| const __va_list_tag | SpecifiedType | | __va_list_tag | | |
| const __va_list_tag & | LValueReferenceType | | const __va_list_tag | | |
| const address | SpecifiedType | | address | | |
| const address & | LValueReferenceType | | const address | | |
| const char | SpecifiedType | | char | | |
| const char * | PointerType | | const char | | |
| const char *[3] | ArrayType | const char * | const char * | | |
| const char *[] | ArrayType | const char * | const char * | | |
| const char[5] | ArrayType | const char | const char | | |
| const char[6] | ArrayType | const char | const char | | |
| const char[8] | ArrayType | const char | const char | | |
| const char[9] | ArrayType | const char | const char | | |
| const char[10] | ArrayType | const char | const char | | |
| const char[53] | ArrayType | const char | const char | | |
| const double | SpecifiedType | | double | | |
| const int | SpecifiedType | | int | | |
| decltype(nullptr) | NullPointerType | | | | |
| double | DoubleType | | | | |
| error | ErroneousType | | | | |
| float | FloatType | | | | |
| float[3] | ArrayType | float | float | | |
| int | IntType, MicrosoftInt32Type | | | | |
| int * | IntPointerType | | int | | |
| int[4] | ArrayType | int | int | | |
| int[8] | ArrayType | int | int | | |
| int[10] | ArrayType | int | int | | |
| int[10][20] | ArrayType | int[20] | int[20] | | |
| int[20] | ArrayType | int | int | | |
| int[] | ArrayType | int | int | | |
| long | LongType | | | | |
| long double | LongDoubleType | | | | |
| long long | LongLongType, MicrosoftInt64Type | | | | |
| short | MicrosoftInt16Type, ShortType | | | | |
| signed __int128 | Int128Type | | | | |
| signed char | SignedCharType | | | | |
| signed int | IntType | | | | |
| signed long | LongType | | | | |
| signed long long | LongLongType | | | | |
| signed short | ShortType | | | | |
| unknown | UnknownType | | | | |
| unsigned __int128 | Int128Type | | | | unsigned integral |
| unsigned char | UnsignedCharType | | | | unsigned integral |
| unsigned int | IntType | | | unsigned int | unsigned integral |
| unsigned long | LongType | | | | unsigned integral |
| unsigned long long | LongLongType | | | | unsigned integral |
| unsigned short | ShortType | | | | unsigned integral |
| void | VoidType | | | | |
| void * | VoidPointerType | | void | | |
| wchar_t | Wchar_t, WideCharType | | | | |
| ..()(..) | PrintableElement, RoutineDumpType | | | | |
| ..(*)(..) | FunctionPointerDumpType, PrintableElement | | ..()(..) | | |
| _Complex __float128 | BinaryFloatingPointType, BuiltInDumpType, ComplexNumberType, PrintableElement | | | | |
| _Complex double | BinaryFloatingPointType, BuiltInDumpType, ComplexNumberType, PrintableElement | | | | |
| _Complex float | BinaryFloatingPointType, BuiltInDumpType, ComplexNumberType, PrintableElement | | | | |
| _Complex long double | BinaryFloatingPointType, BuiltInDumpType, ComplexNumberType, PrintableElement | | | | |
| _Decimal32 | BuiltInDumpType, Decimal32Type, PrintableElement | | | | |
| _Decimal64 | BuiltInDumpType, Decimal64Type, PrintableElement | | | | |
| _Decimal128 | BuiltInDumpType, Decimal128Type, PrintableElement | | | | |
| _Float32 | BinaryFloatingPointType, BuiltInDumpType, PrintableElement, RealNumberType | | | | |
| _Float32x | BinaryFloatingPointType, BuiltInDumpType, PrintableElement, RealNumberType | | | | |
| _Float64 | BinaryFloatingPointType, BuiltInDumpType, PrintableElement, RealNumberType | | | | |
| _Float64x | BinaryFloatingPointType, BuiltInDumpType, PrintableElement, RealNumberType | | | | |
| _Float128 | BinaryFloatingPointType, BuiltInDumpType, PrintableElement, RealNumberType | | | | |
| _Float128x | BinaryFloatingPointType, BuiltInDumpType, PrintableElement, RealNumberType | | | | |
| _Imaginary double | BinaryFloatingPointType, BuiltInDumpType, ImaginaryNumberType, PrintableElement | | | | |
| _Imaginary float | BinaryFloatingPointType, BuiltInDumpType, ImaginaryNumberType, PrintableElement | | | | |
| _Imaginary long double | BinaryFloatingPointType, BuiltInDumpType, ImaginaryNumberType, PrintableElement | | | | |
| __float128 | BuiltInDumpType, Float128Type, PrintableElement | | | | |
| __int128 | Int128Type, IntegralDumpType, PrintableElement | | | | |
| __va_list_tag | DirectAccessHolder, MetricClass, PrintableElement, Struct, StructLikeClass, UserDumpType | | | | |
| __va_list_tag & | LValueReferenceDumpType, PrintableElement | | __va_list_tag | | |
| __va_list_tag && | PrintableElement, RValueReferenceDumpType | | __va_list_tag | | |
| address | DirectAccessHolder, MetricClass, PrintableElement, Struct, StructLikeClass, UserDumpType | | | | |
| address & | LValueReferenceDumpType, PrintableElement | | address | | |
| address && | PrintableElement, RValueReferenceDumpType | | address | | |
| auto | AutoType, PrintableElement, UserDumpType | | | | |
| bool | BoolType, IntegralDumpType, PrintableElement | | | | |
| char | IntegralDumpType, MicrosoftInt8Type, PlainCharType, PrintableElement | | | | |
| char8_t | Char8Type, IntegralDumpType, PrintableElement | | | | |
| char16_t | Char16Type, IntegralDumpType, PrintableElement | | | | |
| char32_t | Char32Type, IntegralDumpType, PrintableElement | | | | |
| char * | CharPointerType, PointerDumpType, PrintableElement | | char | | |
| char *[3] | ArrayDumpType, PrintableElement | char * | char * | | |
| char *[32] | ArrayDumpType, PrintableElement | char * | char * | | |
| char *[] | ArrayDumpType, PrintableElement | char * | char * | | |
| char[2] | ArrayDumpType, PrintableElement | char | char | | |
| char[3] | ArrayDumpType, PrintableElement | char | char | | |
| char[5] | ArrayDumpType, PrintableElement | char | char | | |
| char[6] | ArrayDumpType, PrintableElement | char | char | | |
| char[8] | ArrayDumpType, PrintableElement | char | char | | |
| char[9] | ArrayDumpType, PrintableElement | char | char | | |
| char[10] | ArrayDumpType, PrintableElement | char | char | | |
| char[53] | ArrayDumpType, PrintableElement | char | char | | |
| char[] | ArrayDumpType, PrintableElement | char | char | | |
| const __va_list_tag | PrintableElement, SpecifiedDumpType | | __va_list_tag | | |
| const __va_list_tag & | LValueReferenceDumpType, PrintableElement | | const __va_list_tag | | |
| const address | PrintableElement, SpecifiedDumpType | | address | | |
| const address & | LValueReferenceDumpType, PrintableElement | | const address | | |
| const char | PrintableElement, SpecifiedDumpType | | char | | |
| const char * | PointerDumpType, PrintableElement | | const char | | |
| const char *[3] | ArrayDumpType, PrintableElement | const char * | const char * | | |
| const char *[] | ArrayDumpType, PrintableElement | const char * | const char * | | |
| const char[5] | ArrayDumpType, PrintableElement | const char | const char | | |
| const char[6] | ArrayDumpType, PrintableElement | const char | const char | | |
| const char[8] | ArrayDumpType, PrintableElement | const char | const char | | |
| const char[9] | ArrayDumpType, PrintableElement | const char | const char | | |
| const char[10] | ArrayDumpType, PrintableElement | const char | const char | | |
| const char[53] | ArrayDumpType, PrintableElement | const char | const char | | |
| const double | PrintableElement, SpecifiedDumpType | | double | | |
| const int | PrintableElement, SpecifiedDumpType | | int | | |
| decltype(nullptr) | BuiltInDumpType, NullPointerType, PrintableElement | | | | |
| double | BuiltInDumpType, DoubleType, PrintableElement | | | | |
| error | BuiltInDumpType, ErroneousType, PrintableElement | | | | |
| float | BuiltInDumpType, FloatType, PrintableElement | | | | |
| float[3] | ArrayDumpType, PrintableElement | float | float | | |
| int | IntType, IntegralDumpType, MicrosoftInt32Type, PrintableElement | | | | |
| int * | IntPointerType, PointerDumpType, PrintableElement | | int | | |
| int[4] | ArrayDumpType, PrintableElement | int | int | | |
| int[8] | ArrayDumpType, PrintableElement | int | int | | |
| int[10] | ArrayDumpType, PrintableElement | int | int | | |
| int[10][20] | ArrayDumpType, PrintableElement | int[20] | int[20] | | |
| int[20] | ArrayDumpType, PrintableElement | int | int | | |
| int[] | ArrayDumpType, PrintableElement | int | int | | |
| long | IntegralDumpType, LongType, PrintableElement | | | | |
| long double | BuiltInDumpType, LongDoubleType, PrintableElement | | | | |
| long long | IntegralDumpType, LongLongType, MicrosoftInt64Type, PrintableElement | | | | |
| short | IntegralDumpType, MicrosoftInt16Type, PrintableElement, ShortType | | | | |
| signed __int128 | Int128Type, IntegralDumpType, PrintableElement | | | | |
| signed char | IntegralDumpType, PrintableElement, SignedCharType | | | | |
| signed int | IntType, IntegralDumpType, PrintableElement | | | | |
| signed long | IntegralDumpType, LongType, PrintableElement | | | | |
| signed long long | IntegralDumpType, LongLongType, PrintableElement | | | | |
| signed short | IntegralDumpType, PrintableElement, ShortType | | | | |
| unknown | BuiltInDumpType, PrintableElement, UnknownType | | | | |
| unsigned __int128 | Int128Type, IntegralDumpType, PrintableElement | | | | unsigned integral |
| unsigned char | IntegralDumpType, PrintableElement, UnsignedCharType | | | | unsigned integral |
| unsigned int | IntType, IntegralDumpType, PrintableElement | | | unsigned int | unsigned integral |
| unsigned long | IntegralDumpType, LongType, PrintableElement | | | | unsigned integral |
| unsigned long long | IntegralDumpType, LongLongType, PrintableElement | | | | unsigned integral |
| unsigned short | IntegralDumpType, PrintableElement, ShortType | | | | unsigned integral |
| void | BuiltInDumpType, PrintableElement, VoidType | | | | |
| void * | PointerDumpType, PrintableElement, VoidPointerType | | void | | |
| wchar_t | IntegralDumpType, PrintableElement, Wchar_t, WideCharType | | | | |

View File

@@ -1,70 +1,111 @@
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | __va_list_tag && | DumpVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | __va_list_tag && | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | address && | DumpVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | address && | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const __va_list_tag & | DumpVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const __va_list_tag & | SemanticStackVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const address & | DumpVariable | | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const address & | SemanticStackVariable | | |
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | DumpVariable | | |
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | Field | | |
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | DumpVariable | | |
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | Field | | |
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | DumpVariable | | |
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | Field | | |
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | DumpVariable | | |
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | Field | | |
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | DumpVariable | | |
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | GlobalVariable | | |
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | DumpVariable | | |
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | GlobalVariable | | |
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | DumpVariable | | |
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | GlobalVariable | | |
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
| variables.cpp:5:11:5:11 | c | file://:0:0:0:0 | const int | DumpVariable | const | static |
| variables.cpp:5:11:5:11 | c | file://:0:0:0:0 | const int | GlobalVariable | const | static |
| variables.cpp:5:11:5:11 | c | file://:0:0:0:0 | const int | StaticStorageDurationVariable | const | static |
| variables.cpp:6:14:6:15 | pi | file://:0:0:0:0 | const double | DumpVariable | const | static |
| variables.cpp:6:14:6:15 | pi | file://:0:0:0:0 | const double | GlobalVariable | const | static |
| variables.cpp:6:14:6:15 | pi | file://:0:0:0:0 | const double | StaticStorageDurationVariable | const | static |
| variables.cpp:8:10:8:10 | a | file://:0:0:0:0 | unsigned int | DumpVariable | | |
| variables.cpp:8:10:8:10 | a | file://:0:0:0:0 | unsigned int | GlobalVariable | | |
| variables.cpp:8:10:8:10 | a | file://:0:0:0:0 | unsigned int | StaticStorageDurationVariable | | |
| variables.cpp:10:14:10:14 | b | file://:0:0:0:0 | unsigned int | DumpVariable | | |
| variables.cpp:10:14:10:14 | b | file://:0:0:0:0 | unsigned int | GlobalVariable | | |
| variables.cpp:10:14:10:14 | b | file://:0:0:0:0 | unsigned int | StaticStorageDurationVariable | | |
| variables.cpp:12:13:12:17 | kings | file://:0:0:0:0 | const char *[] | DumpVariable | | |
| variables.cpp:12:13:12:17 | kings | file://:0:0:0:0 | const char *[] | GlobalVariable | | |
| variables.cpp:12:13:12:17 | kings | file://:0:0:0:0 | const char *[] | StaticStorageDurationVariable | | |
| variables.cpp:14:6:14:6 | p | file://:0:0:0:0 | int * | DumpVariable | | |
| variables.cpp:14:6:14:6 | p | file://:0:0:0:0 | int * | GlobalVariable | | |
| variables.cpp:14:6:14:6 | p | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
| variables.cpp:14:9:14:9 | q | file://:0:0:0:0 | int | DumpVariable | | |
| variables.cpp:14:9:14:9 | q | file://:0:0:0:0 | int | GlobalVariable | | |
| variables.cpp:14:9:14:9 | q | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
| variables.cpp:15:12:15:13 | v1 | file://:0:0:0:0 | int[10] | DumpVariable | | static |
| variables.cpp:15:12:15:13 | v1 | file://:0:0:0:0 | int[10] | GlobalVariable | | static |
| variables.cpp:15:12:15:13 | v1 | file://:0:0:0:0 | int[10] | StaticStorageDurationVariable | | static |
| variables.cpp:15:21:15:22 | pv | file://:0:0:0:0 | int * | DumpVariable | | static |
| variables.cpp:15:21:15:22 | pv | file://:0:0:0:0 | int * | GlobalVariable | | static |
| variables.cpp:15:21:15:22 | pv | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | static |
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | DumpVariable | | |
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | FunctionPointerVariable | | |
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | GlobalVariable | | |
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | StaticStorageDurationVariable | | |
| variables.cpp:19:7:19:8 | v2 | file://:0:0:0:0 | float[3] | DumpVariable | | |
| variables.cpp:19:7:19:8 | v2 | file://:0:0:0:0 | float[3] | GlobalVariable | | |
| variables.cpp:19:7:19:8 | v2 | file://:0:0:0:0 | float[3] | StaticStorageDurationVariable | | |
| variables.cpp:20:7:20:8 | v3 | file://:0:0:0:0 | char *[32] | DumpVariable | | |
| variables.cpp:20:7:20:8 | v3 | file://:0:0:0:0 | char *[32] | GlobalVariable | | |
| variables.cpp:20:7:20:8 | v3 | file://:0:0:0:0 | char *[32] | StaticStorageDurationVariable | | |
| variables.cpp:22:5:22:6 | d2 | file://:0:0:0:0 | int[10][20] | DumpVariable | | |
| variables.cpp:22:5:22:6 | d2 | file://:0:0:0:0 | int[10][20] | GlobalVariable | | |
| variables.cpp:22:5:22:6 | d2 | file://:0:0:0:0 | int[10][20] | StaticStorageDurationVariable | | |
| variables.cpp:24:6:24:7 | v4 | file://:0:0:0:0 | char[3] | DumpVariable | | |
| variables.cpp:24:6:24:7 | v4 | file://:0:0:0:0 | char[3] | GlobalVariable | | |
| variables.cpp:24:6:24:7 | v4 | file://:0:0:0:0 | char[3] | StaticStorageDurationVariable | | |
| variables.cpp:26:5:26:6 | v5 | file://:0:0:0:0 | int[8] | DumpVariable | | |
| variables.cpp:26:5:26:6 | v5 | file://:0:0:0:0 | int[8] | GlobalVariable | | |
| variables.cpp:26:5:26:6 | v5 | file://:0:0:0:0 | int[8] | StaticStorageDurationVariable | | |
| variables.cpp:28:7:28:8 | p2 | file://:0:0:0:0 | char * | DumpVariable | | |
| variables.cpp:28:7:28:8 | p2 | file://:0:0:0:0 | char * | GlobalVariable | | |
| variables.cpp:28:7:28:8 | p2 | file://:0:0:0:0 | char * | StaticStorageDurationVariable | | |
| variables.cpp:29:6:29:7 | p3 | file://:0:0:0:0 | char[] | DumpVariable | | |
| variables.cpp:29:6:29:7 | p3 | file://:0:0:0:0 | char[] | GlobalVariable | | |
| variables.cpp:29:6:29:7 | p3 | file://:0:0:0:0 | char[] | StaticStorageDurationVariable | | |
| variables.cpp:31:6:31:10 | alpha | file://:0:0:0:0 | char[] | DumpVariable | | |
| variables.cpp:31:6:31:10 | alpha | file://:0:0:0:0 | char[] | GlobalVariable | | |
| variables.cpp:31:6:31:10 | alpha | file://:0:0:0:0 | char[] | StaticStorageDurationVariable | | |
| variables.cpp:34:5:34:6 | av | file://:0:0:0:0 | int[] | DumpVariable | | |
| variables.cpp:34:5:34:6 | av | file://:0:0:0:0 | int[] | GlobalVariable | | |
| variables.cpp:34:5:34:6 | av | file://:0:0:0:0 | int[] | StaticStorageDurationVariable | | |
| variables.cpp:35:6:35:8 | ap1 | file://:0:0:0:0 | int * | DumpVariable | | |
| variables.cpp:35:6:35:8 | ap1 | file://:0:0:0:0 | int * | GlobalVariable | | |
| variables.cpp:35:6:35:8 | ap1 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
| variables.cpp:36:6:36:8 | ap2 | file://:0:0:0:0 | int * | DumpVariable | | |
| variables.cpp:36:6:36:8 | ap2 | file://:0:0:0:0 | int * | GlobalVariable | | |
| variables.cpp:36:6:36:8 | ap2 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | DumpVariable | | |
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | GlobalVariable | | |
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | DumpVariable | | |
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | LocalVariable | | |
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | SemanticStackVariable | | |
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | DumpVariable | | static |
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | StaticLocalVariable | | static |
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | DumpVariable | | |
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | DumpVariable | | |
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | Field | | |
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | DumpVariable | | |
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | DumpVariable | | |
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | DumpVariable | | static |
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable | | static |
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | StaticStorageDurationVariable | | static |
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | DumpVariable | | |
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalVariable | | |
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |

View File

@@ -3,12 +3,8 @@
| tests.cpp:21:15:21:21 | Hello | This argument should be of type 'char16_t *' but is of type 'char *' |
| tests.cpp:21:15:21:21 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *' |
| tests.cpp:26:17:26:24 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
| tests.cpp:27:17:27:24 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
| tests.cpp:29:17:29:23 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *' |
| tests.cpp:30:17:30:24 | Hello | This argument should be of type 'wchar_t *' but is of type 'char16_t *' |
| tests.cpp:34:36:34:43 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
| tests.cpp:35:36:35:43 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
| tests.cpp:37:36:37:42 | Hello | This argument should be of type 'char16_t *' but is of type 'char *' |
| tests.cpp:39:36:39:43 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |
| tests.cpp:42:37:42:44 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
| tests.cpp:43:37:43:44 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |

View File

@@ -24,17 +24,17 @@ void tests() {
wprintf(L"%s", "Hello"); // GOOD
wprintf(L"%s", u"Hello"); // BAD: expecting char
wprintf(L"%s", L"Hello"); // BAD: expecting char
wprintf(L"%s", L"Hello"); // BAD: expecting char [NOT DETECTED; correct on Microsoft platforms]
wprintf(L"%S", "Hello"); // BAD: expecting wchar_t
wprintf(L"%S", "Hello"); // BAD: expecting wchar_t [NOT DETECTED; correct on Microsoft platforms]
wprintf(L"%S", u"Hello"); // BAD: expecting wchar_t
wprintf(L"%S", L"Hello"); // GOOD
swprintf(buffer, BUF_SIZE, u"%s", "Hello"); // GOOD
swprintf(buffer, BUF_SIZE, u"%s", u"Hello"); // BAD: expecting char
swprintf(buffer, BUF_SIZE, u"%s", u"Hello"); // BAD: expecting char [NOT DETECTED; correct on Microsoft platforms]
swprintf(buffer, BUF_SIZE, u"%s", L"Hello"); // BAD: expecting char
swprintf(buffer, BUF_SIZE, u"%S", "Hello"); // BAD: expecting char16_t
swprintf(buffer, BUF_SIZE, u"%S", "Hello"); // BAD: expecting char16_t [NOT DETECTED; correct on Microsoft platforms]
swprintf(buffer, BUF_SIZE, u"%S", u"Hello"); // GOOD
swprintf(buffer, BUF_SIZE, u"%S", L"Hello"); // BAD: expecting char16_t

View File

@@ -1,3 +1,2 @@
| printf.cpp:31:31:31:37 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:43:29:43:35 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:50:29:50:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |

View File

@@ -28,7 +28,7 @@ int sprintf(char *dest, char *format, ...);
void test1() {
WCHAR string[20];
swprintf(string, u"test %s", u"test"); // BAD: `char16_t` string parameter read as `char` string
swprintf(string, u"test %s", u"test"); // BAD: `char16_t` string parameter read as `char` string [NOT DETECTED; correct on Microsoft platforms]
}
void test2() {

View File

@@ -11,8 +11,6 @@
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int' |
| printf1.h:154:18:154:19 | wc | This argument should be of type 'char *' but is of type 'wchar_t *' |
| printf1.h:155:18:155:18 | c | This argument should be of type 'wchar_t *' but is of type 'char *' |
| printf1.h:168:19:168:19 | i | This argument should be of type 'long long' but is of type 'int' |
| printf1.h:169:19:169:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |

View File

@@ -151,8 +151,8 @@ void test_chars(char c, wchar_t wc, wint_t wt)
void test_ws(char *c, wchar_t *wc)
{
wprintf(L"%s", c); // GOOD
wprintf(L"%s", wc); // BAD
wprintf(L"%S", c); // BAD
wprintf(L"%s", wc); // BAD [NOT DETECTED; correct on Microsoft platforms]
wprintf(L"%S", c); // BAD [NOT DETECTED; correct on Microsoft platforms]
wprintf(L"%S", wc); // GOOD
}

View File

@@ -19,8 +19,6 @@
| printf1.h:116:16:116:24 | myString3 | This argument should be of type '__wchar_t *' but is of type 'int *' |
| printf1.h:117:16:117:24 | myString4 | This argument should be of type '__wchar_t *' but is of type 'int *' |
| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int' |
| printf1.h:153:18:153:18 | c | This argument should be of type '__wchar_t *' but is of type 'char *' |
| printf1.h:156:18:156:19 | wc | This argument should be of type 'char *' but is of type '__wchar_t *' |
| printf1.h:181:21:181:22 | ll | This argument should be of type 'int' but is of type 'long long' |
| printf1.h:182:21:182:23 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:185:21:185:23 | i64 | This argument should be of type 'int' but is of type 'long long' |

View File

@@ -150,10 +150,10 @@ void test_chars(char c, wchar_t wc, wint_t wt)
void test_ws(char *c, wchar_t *wc, wint_t *wt)
{
wprintf(L"%s", c); // BAD
wprintf(L"%s", c); // BAD [NOT DETECTED; correct on non-Microsoft platforms]
wprintf(L"%s", wc); // GOOD
wprintf(L"%S", c); // GOOD
wprintf(L"%S", wc); // BAD
wprintf(L"%S", wc); // BAD [NOT DETECTED; correct on non-Microsoft platforms]
}
void fun4()

View File

@@ -7,3 +7,4 @@
| test.cpp:170:6:170:9 | data | Memory pointed to by 'data' may have been previously freed $@ | test.cpp:165:2:165:5 | call to free | here |
| test.cpp:193:6:193:9 | data | Memory pointed to by 'data' may have been previously freed $@ | test.cpp:191:3:191:6 | call to free | here |
| test.cpp:201:6:201:6 | x | Memory pointed to by 'x' may have been previously freed $@ | test.cpp:200:2:200:9 | delete | here |
| test.cpp:242:14:242:17 | data | Memory pointed to by 'data' may have been previously freed $@ | test.cpp:243:11:243:14 | call to free | here |

View File

@@ -213,3 +213,42 @@ void regression_test_for_static_var_handling()
data = (char *)malloc(100*sizeof(char));
use(data); // GOOD
}
void test16(int n, bool b) {
char* data = NULL;
for(int i = 0; i < n; ++i) {
if(b) data = (char*)malloc(10 * sizeof(char));
if(!b || data == NULL) return;
use(data); // GOOD
free(data); // GOOD
}
}
void test17(int n, bool b) {
char* data = (char*)malloc(10);
if(b) {
free(data);
}
if(!b) {
use(data); // GOOD
}
}
void test18(int* array) {
char* data = (char*)malloc(10 * sizeof(char));
for (int i = 0; i < 4; ++i) {
int b = array[i];
if(b) use(data); // BAD
if(!b) free(data);
}
}
void test19(int* array) {
char* data = (char*)malloc(10 * sizeof(char));
int b = array[0];
for (int i = 0; i < 4; ++i) {
if(b) use(data); // GOOD
if(!b) free(data);
}
}

View File

@@ -8,7 +8,6 @@
| test.cpp:132:9:132:9 | j | The variable $@ may not be initialized here. | test.cpp:126:6:126:6 | j | j |
| test.cpp:219:3:219:3 | x | The variable $@ may not be initialized here. | test.cpp:218:7:218:7 | x | x |
| test.cpp:243:13:243:13 | i | The variable $@ may not be initialized here. | test.cpp:241:6:241:6 | i | i |
| test.cpp:329:9:329:11 | val | The variable $@ may not be initialized here. | test.cpp:321:6:321:8 | val | val |
| test.cpp:336:10:336:10 | a | The variable $@ may not be initialized here. | test.cpp:333:7:333:7 | a | a |
| test.cpp:369:10:369:10 | a | The variable $@ may not be initialized here. | test.cpp:358:7:358:7 | a | a |
| test.cpp:378:9:378:11 | val | The variable $@ may not be initialized here. | test.cpp:359:6:359:8 | val | val |

View File

@@ -326,7 +326,7 @@ int test28() {
a = false;
c = false;
}
return val; // GOOD [FALSE POSITIVE]
return val; // GOOD
}
int test29() {

View File

@@ -5,8 +5,8 @@
<overview>
<p>Relying on <code>HttpRequest</code> to provide access to a particular client variable is not
safe. The <code>HttpRequest</code> class implements an indexer to provide a simplified, combined
access to its <code>QueryString</code>, <code>Form</code>, <code>Cookies</code>, or <code>
ServerVariables</code> collections, in that particular order. When searching for a variable, the
access to its <code>QueryString</code>, <code>Form</code>, <code>Cookies</code>, or
<code>ServerVariables</code> collections, in that particular order. When searching for a variable, the
first match is returned: <code>QueryString</code> parameters hence supersede values from forms,
cookies and server variables, and so on. This is a serious attack vector since an attacker could
inject a value in the query string that you do not expect, and which supersedes the value of a more

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -1117,6 +1117,44 @@ ReturnPosition getReturnPosition(ReturnNodeExt ret) {
result = getReturnPosition0(ret, ret.getKind())
}
/**
* Checks whether `inner` can return to `call` in the call context `innercc`.
* Assumes a context of `inner = viableCallableExt(call)`.
*/
bindingset[innercc, inner, call]
predicate checkCallContextReturn(CallContext innercc, DataFlowCallable inner, DataFlowCall call) {
innercc instanceof CallContextAny
or
exists(DataFlowCallable c0, DataFlowCall call0 |
callEnclosingCallable(call0, inner) and
innercc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
}
/**
* Checks whether `call` can resolve to `calltarget` in the call context `cc`.
* Assumes a context of `calltarget = viableCallableExt(call)`.
*/
bindingset[cc, call, calltarget]
predicate checkCallContextCall(CallContext cc, DataFlowCall call, DataFlowCallable calltarget) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
if reducedViableImplInCallContext(call, _, ctx)
then calltarget = prunedViableImplInCallContext(call, ctx)
else any()
)
or
cc instanceof CallContextSomeCall
or
cc instanceof CallContextAny
or
cc instanceof CallContextReturn
}
/**
* Resolves a return from `callable` in `cc` to `call`. This is equivalent to
* `callable = viableCallableExt(call) and checkCallContextReturn(cc, callable, call)`.
*/
bindingset[cc, callable]
predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) {
cc instanceof CallContextAny and callable = viableCallableExt(call)
@@ -1128,6 +1166,10 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
)
}
/**
* Resolves a call from `call` in `cc` to `result`. This is equivalent to
* `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`.
*/
bindingset[call, cc]
DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* SQL-injection vulnerabilities relating to the `org.springframework.jdbc.object` are now recognised.

View File

@@ -1,6 +1,6 @@
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:header-splitting,sink:information-leak,sink:jexl,sink:ldap,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:xpath,sink:xss,source:remote,summary:taint,summary:value
android.content,8,,,,,,,,,,,8,,,,,,,
android.database,59,,,,,,,,,,,59,,,,,,,
android.content,8,,4,,,,,,,,,8,,,,,,4,
android.database,59,,30,,,,,,,,,59,,,,,,30,
android.util,,16,,,,,,,,,,,,,,,16,,
android.webkit,3,2,,,,,,,,,,,,,,3,2,,
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,1,
@@ -27,7 +27,7 @@ javax.ws.rs.core,3,,143,,,1,,,,,,,,2,,,,88,55
javax.xml.transform.sax,,,4,,,,,,,,,,,,,,,4,
javax.xml.transform.stream,,,2,,,,,,,,,,,,,,,2,
javax.xml.xpath,3,,,,,,,,,,,,,,3,,,,
org.apache.commons.codec,,,2,,,,,,,,,,,,,,,2,
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,6,
org.apache.commons.collections,,,99,,,,,,,,,,,,,,,4,95
org.apache.commons.collections4,,,99,,,,,,,,,,,,,,,4,95
org.apache.commons.io,,,22,,,,,,,,,,,,,,,22,
@@ -46,15 +46,17 @@ org.dom4j,20,,,,,,,,,,,,,,20,,,,
org.hibernate,7,,,,,,,,,,,7,,,,,,,
org.jooq,1,,,,,,,,,,,1,,,,,,,
org.springframework.beans,,,26,,,,,,,,,,,,,,,,26
org.springframework.cache,,,13,,,,,,,,,,,,,,,,13
org.springframework.http,14,,,,,,,,,14,,,,,,,,,
org.springframework.jdbc.core,10,,,,,,,,,,,10,,,,,,,
org.springframework.ldap.core,14,,,,,,,,14,,,,,,,,,,
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,6,,
org.springframework.ui,,,32,,,,,,,,,,,,,,,,32
org.springframework.util,,,139,,,,,,,,,,,,,,,87,52
org.springframework.validation,,,13,,,,,,,,,,,,,,,13,
org.springframework.web.client,13,3,,,,,,,,13,,,,,,,3,,
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,8,,
org.springframework.web.multipart,,12,,,,,,,,,,,,,,,12,,
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,12,13,
org.springframework.web.reactive.function.client,2,,,,,,,,,2,,,,,,,,,
org.xml.sax,,,1,,,,,,,,,,,,,,,1,
org.xmlpull.v1,,3,,,,,,,,,,,,,,,3,,
1 package sink source summary sink:bean-validation sink:create-file sink:header-splitting sink:information-leak sink:jexl sink:ldap sink:open-url sink:set-hostname-verifier sink:sql sink:url-open-stream sink:url-redirect sink:xpath sink:xss source:remote summary:taint summary:value
2 android.content 8 4 8 4
3 android.database 59 30 59 30
4 android.util 16 16
5 android.webkit 3 2 3 2
6 com.esotericsoftware.kryo.io 1 1
27 javax.xml.transform.sax 4 4
28 javax.xml.transform.stream 2 2
29 javax.xml.xpath 3 3
30 org.apache.commons.codec 2 6 2 6
31 org.apache.commons.collections 99 4 95
32 org.apache.commons.collections4 99 4 95
33 org.apache.commons.io 22 22
46 org.hibernate 7 7
47 org.jooq 1 1
48 org.springframework.beans 26 26
49 org.springframework.cache 13 13
50 org.springframework.http 14 14
51 org.springframework.jdbc.core 10 10
52 org.springframework.ldap.core 14 14
53 org.springframework.security.web.savedrequest 6 6
54 org.springframework.ui 32 32
55 org.springframework.util 139 87 52
56 org.springframework.validation 13 13
57 org.springframework.web.client 13 3 13 3
58 org.springframework.web.context.request 8 8
59 org.springframework.web.multipart 12 13 12 13
60 org.springframework.web.reactive.function.client 2 2
61 org.xml.sax 1 1
62 org.xmlpull.v1 3 3

View File

@@ -7,7 +7,7 @@ Java framework & library support
:widths: auto
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE022` :sub:`Path injection`,`CWE036` :sub:`Path traversal`,`CWE079` :sub:`Cross-site scripting`,`CWE089` :sub:`SQL injection`,`CWE090` :sub:`LDAP injection`,`CWE094` :sub:`Code injection`,`CWE319` :sub:`Cleartext transmission`
Android,``android.*``,18,,70,,,3,67,,,
Android,``android.*``,18,34,70,,,3,67,,,
`Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,198,,,,,,,,
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,22,,,,,,,,
`Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,420,,,,,,,,
@@ -16,7 +16,7 @@ Java framework & library support
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,158,6,,6,,,,,
Java Standard Library,``java.*``,3,327,30,13,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",22,294,18,,,,,1,1,2
`Spring <https://spring.io/>`_,``org.springframework.*``,29,178,53,,,,10,14,,29
Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.databind``, ``com.unboundid.ldap.sdk``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,8,82,,,,14,18,,
Totals,,84,2013,287,13,6,6,98,33,1,66
`Spring <https://spring.io/>`_,``org.springframework.*``,29,236,53,,,,10,14,,29
Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.databind``, ``com.unboundid.ldap.sdk``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,12,82,,,,14,18,,
Totals,,84,2109,287,13,6,6,98,33,1,66

View File

@@ -3,6 +3,8 @@
* @description Sensitive cookies without the 'HttpOnly' flag set leaves session cookies vulnerable to
* an XSS attack.
* @kind path-problem
* @problem.severity warning
* @precision medium
* @id java/sensitive-cookie-not-httponly
* @tags security
* external/cwe/cwe-1004

View File

@@ -2,6 +2,8 @@
* @name Cleartext Credentials in Properties File
* @description Finds cleartext credentials in Java properties files.
* @kind problem
* @problem.severity warning
* @precision high
* @id java/credentials-in-properties
* @tags security
* external/cwe/cwe-555

View File

@@ -652,6 +652,48 @@ Element interpretElement(
)
}
private predicate parseField(string c, FieldContent f) {
specSplit(_, c, _) and
exists(string fieldRegex, string package, string className, string fieldName |
fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and
package = c.regexpCapture(fieldRegex, 1) and
className = c.regexpCapture(fieldRegex, 2) and
fieldName = c.regexpCapture(fieldRegex, 3) and
f.getField().hasQualifiedName(package, className, fieldName)
)
}
/** A string representing a synthetic instance field. */
class SyntheticField extends string {
SyntheticField() { parseSynthField(_, this) }
/**
* Gets the type of this field. The default type is `Object`, but this can be
* overridden.
*/
Type getType() { result instanceof TypeObject }
}
private predicate parseSynthField(string c, string f) {
specSplit(_, c, _) and
c.regexpCapture("SyntheticField\\[([.a-zA-Z0-9]+)\\]", 1) = f
}
/** Holds if the specification component parses as a `Content`. */
predicate parseContent(string component, Content content) {
parseField(component, content)
or
parseSynthField(component, content.(SyntheticFieldContent).getField())
or
component = "ArrayElement" and content instanceof ArrayContent
or
component = "Element" and content instanceof CollectionContent
or
component = "MapKey" and content instanceof MapKeyContent
or
component = "MapValue" and content instanceof MapValueContent
}
cached
private module Cached {
/**

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -943,13 +943,8 @@ private module Stage2 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1122,8 +1117,7 @@ private module Stage2 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -1615,13 +1609,8 @@ private module Stage3 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
any()
}
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1816,8 +1805,7 @@ private module Stage3 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)
@@ -2364,20 +2352,16 @@ private module Stage4 {
bindingset[call, c, outercc]
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
c = resolveCall(call, outercc) and
checkCallContextCall(outercc, call, c) and
if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
}
bindingset[call, c]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
checkCallContextReturn(innercc, c, call) and
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[innercc, inner, call]
private predicate checkCallContextReturn(Cc innercc, DataFlowCallable inner, DataFlowCall call) {
resolveReturn(innercc, inner, call)
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, config) and
@@ -2579,8 +2563,7 @@ private module Stage4 {
fwdFlow(ret, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
checkCallContextReturn(innercc, inner, call) and
ccOut = getCallContextReturn(inner, call)
ccOut = getCallContextReturn(inner, call, innercc)
|
ap instanceof ApNil or allowsFieldFlow = true
)

View File

@@ -1117,6 +1117,44 @@ ReturnPosition getReturnPosition(ReturnNodeExt ret) {
result = getReturnPosition0(ret, ret.getKind())
}
/**
* Checks whether `inner` can return to `call` in the call context `innercc`.
* Assumes a context of `inner = viableCallableExt(call)`.
*/
bindingset[innercc, inner, call]
predicate checkCallContextReturn(CallContext innercc, DataFlowCallable inner, DataFlowCall call) {
innercc instanceof CallContextAny
or
exists(DataFlowCallable c0, DataFlowCall call0 |
callEnclosingCallable(call0, inner) and
innercc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
}
/**
* Checks whether `call` can resolve to `calltarget` in the call context `cc`.
* Assumes a context of `calltarget = viableCallableExt(call)`.
*/
bindingset[cc, call, calltarget]
predicate checkCallContextCall(CallContext cc, DataFlowCall call, DataFlowCallable calltarget) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
if reducedViableImplInCallContext(call, _, ctx)
then calltarget = prunedViableImplInCallContext(call, ctx)
else any()
)
or
cc instanceof CallContextSomeCall
or
cc instanceof CallContextAny
or
cc instanceof CallContextReturn
}
/**
* Resolves a return from `callable` in `cc` to `call`. This is equivalent to
* `callable = viableCallableExt(call) and checkCallContextReturn(cc, callable, call)`.
*/
bindingset[cc, callable]
predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) {
cc instanceof CallContextAny and callable = viableCallableExt(call)
@@ -1128,6 +1166,10 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
)
}
/**
* Resolves a call from `call` in `cc` to `result`. This is equivalent to
* `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`.
*/
bindingset[call, cc]
DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |

View File

@@ -162,7 +162,8 @@ private newtype TContent =
TArrayContent() or
TCollectionContent() or
TMapKeyContent() or
TMapValueContent()
TMapValueContent() or
TSyntheticFieldContent(SyntheticField s)
/**
* A description of the way data may be stored inside an object. Examples
@@ -170,6 +171,9 @@ private newtype TContent =
* of an array.
*/
class Content extends TContent {
/** Gets the type of the contained data for the purpose of type pruning. */
abstract DataFlowType getType();
/** Gets a textual representation of this element. */
abstract string toString();
@@ -193,6 +197,8 @@ class FieldContent extends Content, TFieldContent {
InstanceField getField() { result = f }
override DataFlowType getType() { result = getErasedRepr(f.getType()) }
override string toString() { result = f.toString() }
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
@@ -202,24 +208,45 @@ class FieldContent extends Content, TFieldContent {
/** A reference through an array. */
class ArrayContent extends Content, TArrayContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "[]" }
}
/** A reference through the contents of some collection-like container. */
class CollectionContent extends Content, TCollectionContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "<element>" }
}
/** A reference through a map key. */
class MapKeyContent extends Content, TMapKeyContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "<map.key>" }
}
/** A reference through a map value. */
class MapValueContent extends Content, TMapValueContent {
override DataFlowType getType() { result instanceof TypeObject }
override string toString() { result = "<map.value>" }
}
/** A reference through a synthetic instance field. */
class SyntheticFieldContent extends Content, TSyntheticFieldContent {
SyntheticField s;
SyntheticFieldContent() { this = TSyntheticFieldContent(s) }
SyntheticField getField() { result = s }
override DataFlowType getType() { result = getErasedRepr(s.getType()) }
override string toString() { result = s.toString() }
}
/**
* A guard that validates some expression.
*

View File

@@ -23,21 +23,7 @@ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSum
DataFlowCall summaryDataFlowCall(Node receiver) { none() }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) {
result = getErasedRepr(c.(FieldContent).getField().getType())
or
c instanceof CollectionContent and
result instanceof TypeObject
or
c instanceof ArrayContent and
result instanceof TypeObject
or
c instanceof MapKeyContent and
result instanceof TypeObject
or
c instanceof MapValueContent and
result instanceof TypeObject
}
DataFlowType getContentType(Content c) { result = c.getType() }
/** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
@@ -70,29 +56,10 @@ predicate summaryElement(DataFlowCallable c, string input, string output, string
)
}
private FieldContent parseField(string c) {
External::specSplit(_, c, _) and
exists(string fieldRegex, string package, string className, string fieldName |
fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and
package = c.regexpCapture(fieldRegex, 1) and
className = c.regexpCapture(fieldRegex, 2) and
fieldName = c.regexpCapture(fieldRegex, 3) and
result.getField().hasQualifiedName(package, className, fieldName)
)
}
/** Gets the summary component for specification component `c`, if any. */
bindingset[c]
SummaryComponent interpretComponentSpecific(string c) {
result = SummaryComponent::content(parseField(c))
or
c = "ArrayElement" and result = SummaryComponent::content(any(ArrayContent c0))
or
c = "Element" and result = SummaryComponent::content(any(CollectionContent c0))
or
c = "MapKey" and result = SummaryComponent::content(any(MapKeyContent c0))
or
c = "MapValue" and result = SummaryComponent::content(any(MapValueContent c0))
exists(Content content | parseContent(c, content) and result = SummaryComponent::content(content))
}
class SourceOrSinkElement = Top;

View File

@@ -24,7 +24,16 @@ private class SqlSinkCsv extends SinkModelCsv {
"org.springframework.jdbc.core;JdbcTemplate;false;queryForMap;;;Argument[0];sql",
"org.springframework.jdbc.core;JdbcTemplate;false;queryForObject;;;Argument[0];sql",
"org.springframework.jdbc.core;JdbcTemplate;false;queryForRowSet;;;Argument[0];sql",
"org.springframework.jdbc.core;JdbcTemplate;false;queryForStream;;;Argument[0];sql"
"org.springframework.jdbc.core;JdbcTemplate;false;queryForStream;;;Argument[0];sql",
"org.springframework.jdbc.object;BatchSqlUpdate;false;BatchSqlUpdate;;;Argument[1];sql",
"org.springframework.jdbc.object;MappingSqlQuery;false;BatchSqlUpdate;;;Argument[1];sql",
"org.springframework.jdbc.object;MappingSqlQueryWithParameters;false;BatchSqlUpdate;;;Argument[1];sql",
"org.springframework.jdbc.object;RdbmsOperation;true;setSql;;;Argument[0];sql",
"org.springframework.jdbc.object;SqlCall;false;SqlCall;;;Argument[1];sql",
"org.springframework.jdbc.object;SqlFunction;false;SqlFunction;;;Argument[1];sql",
"org.springframework.jdbc.object;SqlQuery;false;SqlQuery;;;Argument[1];sql",
"org.springframework.jdbc.object;SqlUpdate;false;SqlUpdate;;;Argument[1];sql",
"org.springframework.jdbc.object;UpdatableSqlQuery;false;UpdatableSqlQuery;;;Argument[1];sql"
]
}
}

View File

@@ -0,0 +1,44 @@
import java.sql.ResultSet;
import java.util.Map;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.object.BatchSqlUpdate;
import org.springframework.jdbc.object.MappingSqlQueryWithParameters;
import org.springframework.jdbc.object.SqlFunction;
import org.springframework.jdbc.object.SqlUpdate;
import org.springframework.jdbc.object.UpdatableSqlQuery;
public class SpringJdbc {
public static String source() { return null; }
private static class MyUpdatableSqlQuery extends UpdatableSqlQuery<String> {
public MyUpdatableSqlQuery() {
super(null, source()); // $ sqlInjection
}
protected String updateRow(ResultSet rs, int rowNum, Map<?,?> context) {
return null;
}
}
public static void test(JdbcTemplate template) {
new BatchSqlUpdate(null, source()); // $ sqlInjection
new SqlFunction(null, source()); // $ sqlInjection
new SqlUpdate(null, source()); // $ sqlInjection
(new BatchSqlUpdate()).setSql(source()); // $ sqlInjection
template.batchUpdate(source()); // $ sqlInjection
template.batchUpdate(source(), null, 0, null); // $ sqlInjection
template.execute(source()); // $ sqlInjection
template.update(source()); // $ sqlInjection
template.query(source(), (RowMapper)null); // $ sqlInjection
template.queryForList(source()); // $ sqlInjection
template.queryForMap(source()); // $ sqlInjection
template.queryForObject(source(), (Class)null); // $ sqlInjection
template.queryForRowSet(source()); // $ sqlInjection
template.queryForStream(source(), (RowMapper)null); // $ sqlInjection
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/mongodbClient
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/mongodbClient:${testdir}/../../../../../stubs/springframework-5.3.8

View File

@@ -0,0 +1,41 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.QueryInjection
import TestUtilities.InlineExpectationsTest
private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
override predicate isSource(DataFlow::Node src) {
src.asExpr() = any(MethodAccess ma | ma.getMethod().hasName("source"))
}
override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node.getType() instanceof NumberType
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
}
}
class HasFlowTest extends InlineExpectationsTest {
HasFlowTest() { this = "HasFlowTest" }
override string getARelevantTag() { result = "sqlInjection" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "sqlInjection" and
exists(DataFlow::Node src, DataFlow::Node sink, QueryInjectionFlowConfig conf |
conf.hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}

View File

@@ -0,0 +1,15 @@
// Generated automatically from org.springframework.core.NestedRuntimeException for testing purposes
package org.springframework.core;
abstract public class NestedRuntimeException extends RuntimeException
{
protected NestedRuntimeException() {}
public NestedRuntimeException(String p0){}
public NestedRuntimeException(String p0, Throwable p1){}
public String getMessage(){ return null; }
public Throwable getMostSpecificCause(){ return null; }
public Throwable getRootCause(){ return null; }
public boolean contains(Class<? extends Object> p0){ return false; }
}

View File

@@ -0,0 +1,12 @@
// Generated automatically from org.springframework.dao.DataAccessException for testing purposes
package org.springframework.dao;
import org.springframework.core.NestedRuntimeException;
abstract public class DataAccessException extends NestedRuntimeException
{
protected DataAccessException() {}
public DataAccessException(String p0){}
public DataAccessException(String p0, Throwable p1){}
}

View File

@@ -0,0 +1,11 @@
// Generated automatically from org.springframework.jdbc.core.BatchPreparedStatementSetter for testing purposes
package org.springframework.jdbc.core;
import java.sql.PreparedStatement;
public interface BatchPreparedStatementSetter
{
int getBatchSize();
void setValues(PreparedStatement p0, int p1);
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.CallableStatementCallback for testing purposes
package org.springframework.jdbc.core;
import java.sql.CallableStatement;
public interface CallableStatementCallback<T>
{
T doInCallableStatement(CallableStatement p0);
}

View File

@@ -0,0 +1,11 @@
// Generated automatically from org.springframework.jdbc.core.CallableStatementCreator for testing purposes
package org.springframework.jdbc.core;
import java.sql.CallableStatement;
import java.sql.Connection;
public interface CallableStatementCreator
{
CallableStatement createCallableStatement(Connection p0);
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.ConnectionCallback for testing purposes
package org.springframework.jdbc.core;
import java.sql.Connection;
public interface ConnectionCallback<T>
{
T doInConnection(Connection p0);
}

View File

@@ -0,0 +1,89 @@
// Generated automatically from org.springframework.jdbc.core.JdbcOperations for testing purposes
package org.springframework.jdbc.core;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.StatementCallback;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
public interface JdbcOperations
{
<T> List<T> query(PreparedStatementCreator p0, RowMapper<T> p1);
<T> List<T> query(String p0, Object[] p1, RowMapper<T> p2);
<T> List<T> query(String p0, Object[] p1, int[] p2, RowMapper<T> p3);
<T> List<T> query(String p0, PreparedStatementSetter p1, RowMapper<T> p2);
<T> List<T> query(String p0, RowMapper<T> p1);
<T> List<T> query(String p0, RowMapper<T> p1, Object... p2);
<T> List<T> queryForList(String p0, Class<T> p1);
<T> List<T> queryForList(String p0, Class<T> p1, Object... p2);
<T> List<T> queryForList(String p0, Object[] p1, Class<T> p2);
<T> List<T> queryForList(String p0, Object[] p1, int[] p2, Class<T> p3);
<T> Stream<T> queryForStream(PreparedStatementCreator p0, RowMapper<T> p1);
<T> Stream<T> queryForStream(String p0, PreparedStatementSetter p1, RowMapper<T> p2);
<T> Stream<T> queryForStream(String p0, RowMapper<T> p1);
<T> Stream<T> queryForStream(String p0, RowMapper<T> p1, Object... p2);
<T> T execute(CallableStatementCreator p0, CallableStatementCallback<T> p1);
<T> T execute(ConnectionCallback<T> p0);
<T> T execute(PreparedStatementCreator p0, PreparedStatementCallback<T> p1);
<T> T execute(StatementCallback<T> p0);
<T> T execute(String p0, CallableStatementCallback<T> p1);
<T> T execute(String p0, PreparedStatementCallback<T> p1);
<T> T query(PreparedStatementCreator p0, ResultSetExtractor<T> p1);
<T> T query(String p0, Object[] p1, ResultSetExtractor<T> p2);
<T> T query(String p0, Object[] p1, int[] p2, ResultSetExtractor<T> p3);
<T> T query(String p0, PreparedStatementSetter p1, ResultSetExtractor<T> p2);
<T> T query(String p0, ResultSetExtractor<T> p1);
<T> T query(String p0, ResultSetExtractor<T> p1, Object... p2);
<T> T queryForObject(String p0, Class<T> p1);
<T> T queryForObject(String p0, Class<T> p1, Object... p2);
<T> T queryForObject(String p0, Object[] p1, Class<T> p2);
<T> T queryForObject(String p0, Object[] p1, RowMapper<T> p2);
<T> T queryForObject(String p0, Object[] p1, int[] p2, Class<T> p3);
<T> T queryForObject(String p0, Object[] p1, int[] p2, RowMapper<T> p3);
<T> T queryForObject(String p0, RowMapper<T> p1);
<T> T queryForObject(String p0, RowMapper<T> p1, Object... p2);
<T> int[] batchUpdate(String p0, Collection<T> p1, int p2, ParameterizedPreparedStatementSetter<T> p3);
List<Map<String, Object>> queryForList(String p0);
List<Map<String, Object>> queryForList(String p0, Object... p1);
List<Map<String, Object>> queryForList(String p0, Object[] p1, int[] p2);
Map<String, Object> call(CallableStatementCreator p0, List<SqlParameter> p1);
Map<String, Object> queryForMap(String p0);
Map<String, Object> queryForMap(String p0, Object... p1);
Map<String, Object> queryForMap(String p0, Object[] p1, int[] p2);
SqlRowSet queryForRowSet(String p0);
SqlRowSet queryForRowSet(String p0, Object... p1);
SqlRowSet queryForRowSet(String p0, Object[] p1, int[] p2);
int update(PreparedStatementCreator p0);
int update(PreparedStatementCreator p0, KeyHolder p1);
int update(String p0);
int update(String p0, Object... p1);
int update(String p0, Object[] p1, int[] p2);
int update(String p0, PreparedStatementSetter p1);
int[] batchUpdate(String p0, BatchPreparedStatementSetter p1);
int[] batchUpdate(String p0, List<Object[]> p1);
int[] batchUpdate(String p0, List<Object[]> p1, int[] p2);
int[] batchUpdate(String... p0);
void execute(String p0);
void query(PreparedStatementCreator p0, RowCallbackHandler p1);
void query(String p0, Object[] p1, RowCallbackHandler p2);
void query(String p0, Object[] p1, int[] p2, RowCallbackHandler p3);
void query(String p0, PreparedStatementSetter p1, RowCallbackHandler p2);
void query(String p0, RowCallbackHandler p1);
void query(String p0, RowCallbackHandler p1, Object... p2);
}

View File

@@ -0,0 +1,133 @@
// Generated automatically from org.springframework.jdbc.core.JdbcTemplate for testing purposes
package org.springframework.jdbc.core;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.ResultSetSupportingSqlParameter;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.StatementCallback;
import org.springframework.jdbc.support.JdbcAccessor;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations
{
protected <T> RowMapper<T> getSingleColumnRowMapper(Class<T> p0){ return null; }
protected Connection createConnectionProxy(Connection p0){ return null; }
protected DataAccessException translateException(String p0, String p1, SQLException p2){ return null; }
protected Map<String, Object> createResultsMap(){ return null; }
protected Map<String, Object> extractOutputParameters(CallableStatement p0, List<SqlParameter> p1){ return null; }
protected Map<String, Object> extractReturnedResults(CallableStatement p0, List<SqlParameter> p1, List<SqlParameter> p2, int p3){ return null; }
protected Map<String, Object> processResultSet(ResultSet p0, ResultSetSupportingSqlParameter p1){ return null; }
protected PreparedStatementSetter newArgPreparedStatementSetter(Object[] p0){ return null; }
protected PreparedStatementSetter newArgTypePreparedStatementSetter(Object[] p0, int[] p1){ return null; }
protected RowMapper<Map<String, Object>> getColumnMapRowMapper(){ return null; }
protected int update(PreparedStatementCreator p0, PreparedStatementSetter p1){ return 0; }
protected void applyStatementSettings(Statement p0){}
protected void handleWarnings(SQLWarning p0){}
protected void handleWarnings(Statement p0){}
public <T> List<T> query(PreparedStatementCreator p0, RowMapper<T> p1){ return null; }
public <T> List<T> query(String p0, Object[] p1, RowMapper<T> p2){ return null; }
public <T> List<T> query(String p0, Object[] p1, int[] p2, RowMapper<T> p3){ return null; }
public <T> List<T> query(String p0, PreparedStatementSetter p1, RowMapper<T> p2){ return null; }
public <T> List<T> query(String p0, RowMapper<T> p1){ return null; }
public <T> List<T> query(String p0, RowMapper<T> p1, Object... p2){ return null; }
public <T> List<T> queryForList(String p0, Class<T> p1){ return null; }
public <T> List<T> queryForList(String p0, Class<T> p1, Object... p2){ return null; }
public <T> List<T> queryForList(String p0, Object[] p1, Class<T> p2){ return null; }
public <T> List<T> queryForList(String p0, Object[] p1, int[] p2, Class<T> p3){ return null; }
public <T> Stream<T> queryForStream(PreparedStatementCreator p0, PreparedStatementSetter p1, RowMapper<T> p2){ return null; }
public <T> Stream<T> queryForStream(PreparedStatementCreator p0, RowMapper<T> p1){ return null; }
public <T> Stream<T> queryForStream(String p0, PreparedStatementSetter p1, RowMapper<T> p2){ return null; }
public <T> Stream<T> queryForStream(String p0, RowMapper<T> p1){ return null; }
public <T> Stream<T> queryForStream(String p0, RowMapper<T> p1, Object... p2){ return null; }
public <T> T execute(CallableStatementCreator p0, CallableStatementCallback<T> p1){ return null; }
public <T> T execute(ConnectionCallback<T> p0){ return null; }
public <T> T execute(PreparedStatementCreator p0, PreparedStatementCallback<T> p1){ return null; }
public <T> T execute(StatementCallback<T> p0){ return null; }
public <T> T execute(String p0, CallableStatementCallback<T> p1){ return null; }
public <T> T execute(String p0, PreparedStatementCallback<T> p1){ return null; }
public <T> T query(PreparedStatementCreator p0, PreparedStatementSetter p1, ResultSetExtractor<T> p2){ return null; }
public <T> T query(PreparedStatementCreator p0, ResultSetExtractor<T> p1){ return null; }
public <T> T query(String p0, Object[] p1, ResultSetExtractor<T> p2){ return null; }
public <T> T query(String p0, Object[] p1, int[] p2, ResultSetExtractor<T> p3){ return null; }
public <T> T query(String p0, PreparedStatementSetter p1, ResultSetExtractor<T> p2){ return null; }
public <T> T query(String p0, ResultSetExtractor<T> p1){ return null; }
public <T> T query(String p0, ResultSetExtractor<T> p1, Object... p2){ return null; }
public <T> T queryForObject(String p0, Class<T> p1){ return null; }
public <T> T queryForObject(String p0, Class<T> p1, Object... p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, Class<T> p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, RowMapper<T> p2){ return null; }
public <T> T queryForObject(String p0, Object[] p1, int[] p2, Class<T> p3){ return null; }
public <T> T queryForObject(String p0, Object[] p1, int[] p2, RowMapper<T> p3){ return null; }
public <T> T queryForObject(String p0, RowMapper<T> p1){ return null; }
public <T> T queryForObject(String p0, RowMapper<T> p1, Object... p2){ return null; }
public <T> int[] batchUpdate(String p0, Collection<T> p1, int p2, ParameterizedPreparedStatementSetter<T> p3){ return null; }
public JdbcTemplate(){}
public JdbcTemplate(DataSource p0){}
public JdbcTemplate(DataSource p0, boolean p1){}
public List<Map<String, Object>> queryForList(String p0){ return null; }
public List<Map<String, Object>> queryForList(String p0, Object... p1){ return null; }
public List<Map<String, Object>> queryForList(String p0, Object[] p1, int[] p2){ return null; }
public Map<String, Object> call(CallableStatementCreator p0, List<SqlParameter> p1){ return null; }
public Map<String, Object> queryForMap(String p0){ return null; }
public Map<String, Object> queryForMap(String p0, Object... p1){ return null; }
public Map<String, Object> queryForMap(String p0, Object[] p1, int[] p2){ return null; }
public SqlRowSet queryForRowSet(String p0){ return null; }
public SqlRowSet queryForRowSet(String p0, Object... p1){ return null; }
public SqlRowSet queryForRowSet(String p0, Object[] p1, int[] p2){ return null; }
public boolean isIgnoreWarnings(){ return false; }
public boolean isResultsMapCaseInsensitive(){ return false; }
public boolean isSkipResultsProcessing(){ return false; }
public boolean isSkipUndeclaredResults(){ return false; }
public int getFetchSize(){ return 0; }
public int getMaxRows(){ return 0; }
public int getQueryTimeout(){ return 0; }
public int update(PreparedStatementCreator p0){ return 0; }
public int update(PreparedStatementCreator p0, KeyHolder p1){ return 0; }
public int update(String p0){ return 0; }
public int update(String p0, Object... p1){ return 0; }
public int update(String p0, Object[] p1, int[] p2){ return 0; }
public int update(String p0, PreparedStatementSetter p1){ return 0; }
public int[] batchUpdate(String p0, BatchPreparedStatementSetter p1){ return null; }
public int[] batchUpdate(String p0, List<Object[]> p1){ return null; }
public int[] batchUpdate(String p0, List<Object[]> p1, int[] p2){ return null; }
public int[] batchUpdate(String... p0){ return null; }
public void execute(String p0){}
public void query(PreparedStatementCreator p0, RowCallbackHandler p1){}
public void query(String p0, Object[] p1, RowCallbackHandler p2){}
public void query(String p0, Object[] p1, int[] p2, RowCallbackHandler p3){}
public void query(String p0, PreparedStatementSetter p1, RowCallbackHandler p2){}
public void query(String p0, RowCallbackHandler p1){}
public void query(String p0, RowCallbackHandler p1, Object... p2){}
public void setFetchSize(int p0){}
public void setIgnoreWarnings(boolean p0){}
public void setMaxRows(int p0){}
public void setQueryTimeout(int p0){}
public void setResultsMapCaseInsensitive(boolean p0){}
public void setSkipResultsProcessing(boolean p0){}
public void setSkipUndeclaredResults(boolean p0){}
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.ParameterizedPreparedStatementSetter for testing purposes
package org.springframework.jdbc.core;
import java.sql.PreparedStatement;
public interface ParameterizedPreparedStatementSetter<T>
{
void setValues(PreparedStatement p0, T p1);
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.PreparedStatementCallback for testing purposes
package org.springframework.jdbc.core;
import java.sql.PreparedStatement;
public interface PreparedStatementCallback<T>
{
T doInPreparedStatement(PreparedStatement p0);
}

View File

@@ -0,0 +1,11 @@
// Generated automatically from org.springframework.jdbc.core.PreparedStatementCreator for testing purposes
package org.springframework.jdbc.core;
import java.sql.Connection;
import java.sql.PreparedStatement;
public interface PreparedStatementCreator
{
PreparedStatement createPreparedStatement(Connection p0);
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.PreparedStatementSetter for testing purposes
package org.springframework.jdbc.core;
import java.sql.PreparedStatement;
public interface PreparedStatementSetter
{
void setValues(PreparedStatement p0);
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.ResultSetExtractor for testing purposes
package org.springframework.jdbc.core;
import java.sql.ResultSet;
public interface ResultSetExtractor<T>
{
T extractData(ResultSet p0);
}

View File

@@ -0,0 +1,24 @@
// Generated automatically from org.springframework.jdbc.core.ResultSetSupportingSqlParameter for testing purposes
package org.springframework.jdbc.core;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
public class ResultSetSupportingSqlParameter extends SqlParameter
{
protected ResultSetSupportingSqlParameter() {}
public ResultSetExtractor<? extends Object> getResultSetExtractor(){ return null; }
public ResultSetSupportingSqlParameter(String p0, int p1){}
public ResultSetSupportingSqlParameter(String p0, int p1, ResultSetExtractor<? extends Object> p2){}
public ResultSetSupportingSqlParameter(String p0, int p1, RowCallbackHandler p2){}
public ResultSetSupportingSqlParameter(String p0, int p1, RowMapper<? extends Object> p2){}
public ResultSetSupportingSqlParameter(String p0, int p1, String p2){}
public ResultSetSupportingSqlParameter(String p0, int p1, int p2){}
public RowCallbackHandler getRowCallbackHandler(){ return null; }
public RowMapper<? extends Object> getRowMapper(){ return null; }
public boolean isInputValueProvided(){ return false; }
public boolean isResultSetSupported(){ return false; }
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.RowCallbackHandler for testing purposes
package org.springframework.jdbc.core;
import java.sql.ResultSet;
public interface RowCallbackHandler
{
void processRow(ResultSet p0);
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.RowMapper for testing purposes
package org.springframework.jdbc.core;
import java.sql.ResultSet;
public interface RowMapper<T>
{
T mapRow(ResultSet p0, int p1);
}

View File

@@ -0,0 +1,24 @@
// Generated automatically from org.springframework.jdbc.core.SqlParameter for testing purposes
package org.springframework.jdbc.core;
import java.util.List;
public class SqlParameter
{
protected SqlParameter() {}
public Integer getScale(){ return null; }
public SqlParameter(SqlParameter p0){}
public SqlParameter(String p0, int p1){}
public SqlParameter(String p0, int p1, String p2){}
public SqlParameter(String p0, int p1, int p2){}
public SqlParameter(int p0){}
public SqlParameter(int p0, String p1){}
public SqlParameter(int p0, int p1){}
public String getName(){ return null; }
public String getTypeName(){ return null; }
public boolean isInputValueProvided(){ return false; }
public boolean isResultsParameter(){ return false; }
public int getSqlType(){ return 0; }
public static List<SqlParameter> sqlTypesToAnonymousParameterList(int... p0){ return null; }
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.springframework.jdbc.core.StatementCallback for testing purposes
package org.springframework.jdbc.core;
import java.sql.Statement;
public interface StatementCallback<T>
{
T doInStatement(Statement p0);
}

View File

@@ -0,0 +1,22 @@
// Generated automatically from org.springframework.jdbc.core.namedparam.ParsedSql for testing purposes
package org.springframework.jdbc.core.namedparam;
import java.util.List;
public class ParsedSql
{
protected ParsedSql() {}
List<String> getParameterNames(){ return null; }
ParsedSql(String p0){}
String getOriginalSql(){ return null; }
int getNamedParameterCount(){ return 0; }
int getTotalParameterCount(){ return 0; }
int getUnnamedParameterCount(){ return 0; }
int[] getParameterIndexes(int p0){ return null; }
public String toString(){ return null; }
void addNamedParameter(String p0, int p1, int p2){}
void setNamedParameterCount(int p0){}
void setTotalParameterCount(int p0){}
void setUnnamedParameterCount(int p0){}
}

View File

@@ -0,0 +1,24 @@
// Generated automatically from org.springframework.jdbc.object.BatchSqlUpdate for testing purposes
package org.springframework.jdbc.object;
import javax.sql.DataSource;
import org.springframework.jdbc.object.SqlUpdate;
public class BatchSqlUpdate extends SqlUpdate
{
protected boolean supportsLobParameters(){ return false; }
public BatchSqlUpdate(){}
public BatchSqlUpdate(DataSource p0, String p1){}
public BatchSqlUpdate(DataSource p0, String p1, int[] p2){}
public BatchSqlUpdate(DataSource p0, String p1, int[] p2, int p3){}
public int getExecutionCount(){ return 0; }
public int getQueueCount(){ return 0; }
public int update(Object... p0){ return 0; }
public int[] flush(){ return null; }
public int[] getRowsAffected(){ return null; }
public static int DEFAULT_BATCH_SIZE = 0;
public void reset(){}
public void setBatchSize(int p0){}
public void setTrackRowsAffected(boolean p0){}
}

View File

@@ -0,0 +1,16 @@
// Generated automatically from org.springframework.jdbc.object.MappingSqlQuery for testing purposes
package org.springframework.jdbc.object;
import java.sql.ResultSet;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.object.MappingSqlQueryWithParameters;
abstract public class MappingSqlQuery<T> extends MappingSqlQueryWithParameters<T>
{
protected abstract T mapRow(ResultSet p0, int p1);
protected final T mapRow(ResultSet p0, int p1, Object[] p2, Map<? extends Object, ? extends Object> p3){ return null; }
public MappingSqlQuery(){}
public MappingSqlQuery(DataSource p0, String p1){}
}

View File

@@ -0,0 +1,17 @@
// Generated automatically from org.springframework.jdbc.object.MappingSqlQueryWithParameters for testing purposes
package org.springframework.jdbc.object;
import java.sql.ResultSet;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.object.SqlQuery;
abstract public class MappingSqlQueryWithParameters<T> extends SqlQuery<T>
{
protected RowMapper<T> newRowMapper(Object[] p0, Map<? extends Object, ? extends Object> p1){ return null; }
protected abstract T mapRow(ResultSet p0, int p1, Object[] p2, Map<? extends Object, ? extends Object> p3);
public MappingSqlQueryWithParameters(){}
public MappingSqlQueryWithParameters(DataSource p0, String p1){}
}

View File

@@ -0,0 +1,45 @@
// Generated automatically from org.springframework.jdbc.object.RdbmsOperation for testing purposes
package org.springframework.jdbc.object;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
abstract public class RdbmsOperation implements InitializingBean
{
protected List<SqlParameter> getDeclaredParameters(){ return null; }
protected String resolveSql(){ return null; }
protected abstract void compileInternal();
protected boolean allowsUnusedParameters(){ return false; }
protected boolean supportsLobParameters(){ return false; }
protected void checkCompiled(){}
protected void validateNamedParameters(Map<String, ? extends Object> p0){}
protected void validateParameters(Object[] p0){}
public JdbcTemplate getJdbcTemplate(){ return null; }
public RdbmsOperation(){}
public String getSql(){ return null; }
public String[] getGeneratedKeysColumnNames(){ return null; }
public boolean isCompiled(){ return false; }
public boolean isReturnGeneratedKeys(){ return false; }
public boolean isUpdatableResults(){ return false; }
public final void compile(){}
public int getResultSetType(){ return 0; }
public void afterPropertiesSet(){}
public void declareParameter(SqlParameter p0){}
public void setDataSource(DataSource p0){}
public void setFetchSize(int p0){}
public void setGeneratedKeysColumnNames(String... p0){}
public void setJdbcTemplate(JdbcTemplate p0){}
public void setMaxRows(int p0){}
public void setParameters(SqlParameter... p0){}
public void setQueryTimeout(int p0){}
public void setResultSetType(int p0){}
public void setReturnGeneratedKeys(boolean p0){}
public void setSql(String p0){}
public void setTypes(int[] p0){}
public void setUpdatableResults(boolean p0){}
}

Some files were not shown because too many files have changed in this diff Show More