Merge branch 'master' into default-taint-tracking-diff-test

This commit is contained in:
Robert Marsh
2020-02-04 09:50:05 -08:00
700 changed files with 16224 additions and 3303 deletions

View File

@@ -25,7 +25,8 @@ predicate functionUsesFunction(Function source, Function f, File target) {
}
predicate dependencyCount(Function source, File target, int res) {
res = strictcount(Declaration d |
res =
strictcount(Declaration d |
functionUsesVariable(source, d, target) or
functionUsesFunction(source, d, target)
)

View File

@@ -38,14 +38,16 @@ where
n = count(Function f | f.fromSource()).toString()
or
l = "Number of Lines Of Code" and
n = sum(File f, int toSum |
n =
sum(File f, int toSum |
f.fromSource() and toSum = f.getMetrics().getNumberOfLinesOfCode()
|
toSum
).toString()
or
l = "Self-Containedness" and
n = (
n =
(
100 * sum(Class c | c.fromSource() | c.getMetrics().getEfferentSourceCoupling()) /
sum(Class c | c.fromSource() | c.getMetrics().getEfferentCoupling())
).toString() + "%"

View File

@@ -80,11 +80,8 @@ class VariableDeclarationLine extends TVariableDeclarationInfo {
* (that is, the first is 0, the second is 1 and so on).
*/
private int getRank() {
line = rank[result](VariableDeclarationLine vdl, int l |
vdl = TVariableDeclarationLine(c, f, l)
|
l
)
line =
rank[result](VariableDeclarationLine vdl, int l | vdl = TVariableDeclarationLine(c, f, l) | l)
}
/**
@@ -133,7 +130,8 @@ class VariableDeclarationGroup extends VariableDeclarationLine {
* Gets the number of uniquely named `VariableDeclarationEntry`s in this group.
*/
int getCount() {
result = count(VariableDeclarationLine l |
result =
count(VariableDeclarationLine l |
l = getProximateNext*()
|
l.getAVDE().getVariable().getName()
@@ -166,7 +164,8 @@ class ExtClass extends Class {
from ExtClass c, int n, VariableDeclarationGroup vdg, string suffix
where
n = strictcount(string fieldName |
n =
strictcount(string fieldName |
exists(Field f |
f.getDeclaringType() = c and
fieldName = f.getName() and

View File

@@ -50,7 +50,8 @@ class BlockOrNonChild extends Element {
private int getNonContiguousStartRankIn(AffectedFile file) {
// When using `rank` with `order by`, the ranks may not be contiguous.
this = rank[result](BlockOrNonChild boc, int startLine, int startCol |
this =
rank[result](BlockOrNonChild boc, int startLine, int startCol |
boc.getLocation().hasLocationInfo(file.getAbsolutePath(), startLine, startCol, _, _)
|
boc order by startLine, startCol
@@ -58,13 +59,15 @@ class BlockOrNonChild extends Element {
}
int getStartRankIn(AffectedFile file) {
this.getNonContiguousStartRankIn(file) = rank[result](int rnk |
this.getNonContiguousStartRankIn(file) =
rank[result](int rnk |
exists(BlockOrNonChild boc | boc.getNonContiguousStartRankIn(file) = rnk)
)
}
int getNonContiguousEndRankIn(AffectedFile file) {
this = rank[result](BlockOrNonChild boc, int endLine, int endCol |
this =
rank[result](BlockOrNonChild boc, int endLine, int endCol |
boc.getLocation().hasLocationInfo(file.getAbsolutePath(), _, _, endLine, endCol)
|
boc order by endLine, endCol
@@ -79,9 +82,8 @@ predicate emptyBlockContainsNonchild(Block b) {
emptyBlock(_, b) and
exists(BlockOrNonChild c, AffectedFile file |
c.(BlockOrNonChild).getStartRankIn(file) = 1 + b.(BlockOrNonChild).getStartRankIn(file) and
c.(BlockOrNonChild).getNonContiguousEndRankIn(file) < b
.(BlockOrNonChild)
.getNonContiguousEndRankIn(file)
c.(BlockOrNonChild).getNonContiguousEndRankIn(file) <
b.(BlockOrNonChild).getNonContiguousEndRankIn(file)
)
}

View File

@@ -307,7 +307,8 @@ predicate nonTrivialValue(string value, Literal literal) {
}
predicate valueOccurrenceCount(string value, int n) {
n = strictcount(Location loc |
n =
strictcount(Location loc |
exists(Literal lit | lit.getLocation() = loc | nonTrivialValue(value, lit)) and
// Exclude generated files (they do not have the same maintainability
// concerns as ordinary source files)
@@ -338,7 +339,8 @@ predicate check(Literal lit, string value, int n, File f) {
}
predicate checkWithFileCount(string value, int overallCount, int fileCount, File f) {
fileCount = strictcount(Location loc |
fileCount =
strictcount(Location loc |
exists(Literal lit | lit.getLocation() = loc | check(lit, value, overallCount, f))
)
}
@@ -364,7 +366,8 @@ predicate firstOccurrence(Literal lit, string value, int n) {
predicate magicConstant(Literal e, string msg) {
exists(string value, int n |
firstOccurrence(e, value, n) and
msg = "Magic constant: literal '" + value + "' is repeated " + n.toString() +
msg =
"Magic constant: literal '" + value + "' is repeated " + n.toString() +
" times and should be encapsulated in a constant."
)
}

View File

@@ -28,13 +28,15 @@ import cpp
// design question and carries has no safety risk.
predicate generatedCopyAssignment(CopyConstructor cc, string msg) {
cc.getDeclaringType().hasImplicitCopyAssignmentOperator() and
msg = "No matching copy assignment operator in class " + cc.getDeclaringType().getName() +
msg =
"No matching copy assignment operator in class " + cc.getDeclaringType().getName() +
". It is good practice to match a copy constructor with a " + "copy assignment operator."
}
predicate generatedCopyConstructor(CopyAssignmentOperator ca, string msg) {
ca.getDeclaringType().hasImplicitCopyConstructor() and
msg = "No matching copy constructor in class " + ca.getDeclaringType().getName() +
msg =
"No matching copy constructor in class " + ca.getDeclaringType().getName() +
". It is good practice to match a copy assignment operator with a " + "copy constructor."
}

View File

@@ -6,7 +6,7 @@
<overview>
<p>
This rule finds calls to <code>open</code> or <code>socket</code> where there is no corresponding <code>close</code> call in the program analyzed.
This rule finds calls to <code>socket</code> where there is no corresponding <code>close</code> call in the program analyzed.
Leaving descriptors open will cause a resource leak that will persist even after the program terminates.
</p>
@@ -14,7 +14,7 @@ Leaving descriptors open will cause a resource leak that will persist even after
</overview>
<recommendation>
<p>Ensure that all file or socket descriptors allocated by the program are freed before it terminates.</p>
<p>Ensure that all socket descriptors allocated by the program are freed before it terminates.</p>
</recommendation>
<example>

View File

@@ -1,6 +1,6 @@
/**
* @name Open descriptor never closed
* @description Functions that always return before closing the socket or file they opened leak resources.
* @description Functions that always return before closing the socket they opened leak resources.
* @kind problem
* @id cpp/descriptor-never-closed
* @problem.severity warning

View File

@@ -33,7 +33,8 @@ predicate spaceProblem(FunctionCall append, string msg) {
malloc.getASuccessor+() = insert and
insert.getArgument(1) = buffer.getAnAccess() and
insert.getASuccessor+() = append and
msg = "This buffer only contains enough room for '" + buffer.getName() + "' (copied on line " +
msg =
"This buffer only contains enough room for '" + buffer.getName() + "' (copied on line " +
insert.getLocation().getStartLine().toString() + ")"
)
}

View File

@@ -51,7 +51,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
loop.getStmt().getAChild*() = bufaccess.getEnclosingStmt() and
loop.limit() >= bufaccess.bufferSize() and
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
msg = "Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
msg =
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
bufaccess.bufferSize().toString() + " elements."
)
@@ -106,8 +107,9 @@ predicate wrongBufferSize(Expr error, string msg) {
statedSize = min(call.statedSizeValue()) and
statedSize > bufsize and
error = call.statedSizeExpr() and
msg = "Potential buffer-overflow: '" + buf.getName() + "' has size " + bufsize.toString() +
" not " + statedSize + "."
msg =
"Potential buffer-overflow: '" + buf.getName() + "' has size " + bufsize.toString() + " not " +
statedSize + "."
)
}
@@ -121,8 +123,9 @@ predicate outOfBounds(BufferAccess bufaccess, string msg) {
or
access = size and not exists(AddressOfExpr addof | bufaccess = addof.getOperand())
) and
msg = "Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf +
"[" + access.toString() + "]' is accessed here."
msg =
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
access.toString() + "]' is accessed here."
)
}

View File

@@ -23,7 +23,8 @@ predicate important(Function f, string message) {
predicate dubious(Function f, string message) {
not important(f, _) and
exists(Options opts, int used, int total, int percentage |
used = count(FunctionCall fc |
used =
count(FunctionCall fc |
fc.getTarget() = f and not opts.okToIgnoreReturnValue(fc) and not unused(fc)
) and
total = count(FunctionCall fc | fc.getTarget() = f and not opts.okToIgnoreReturnValue(fc)) and

View File

@@ -18,14 +18,13 @@ string getCommentTextCaptioned(Comment c, string caption) {
dontCare = commentBody.regexpFind("\\n[/* \\t\\x0B\\f\\r]*" + caption, _, offset) and
interestingSuffix = commentBody.suffix(offset) and
endOfLine = interestingSuffix.indexOf("\n", 1, 0) and
captionedLine = interestingSuffix
captionedLine =
interestingSuffix
.prefix(endOfLine)
.regexpReplaceAll("^[/*\\s]*" + caption + "\\s*:?", "")
.trim() and
followingLine = interestingSuffix
.prefix(interestingSuffix.indexOf("\n", 2, 0))
.suffix(endOfLine)
.trim() and
followingLine =
interestingSuffix.prefix(interestingSuffix.indexOf("\n", 2, 0)).suffix(endOfLine).trim() and
if captionedLine = ""
then result = caption + " comment"
else

View File

@@ -56,7 +56,8 @@ VariableAccess getAnIncrement(Variable var) {
exists(AssignAddExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0)
or
exists(AssignExpr a | a.getLValue() = result |
a.getRValue() = any(AddExpr ae |
a.getRValue() =
any(AddExpr ae |
ae.getAnOperand() = var.getAnAccess() and
ae.getAnOperand().getValue().toInt() > 0
)
@@ -72,7 +73,8 @@ VariableAccess getADecrement(Variable var) {
exists(AssignSubExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0)
or
exists(AssignExpr a | a.getLValue() = result |
a.getRValue() = any(SubExpr ae |
a.getRValue() =
any(SubExpr ae |
ae.getLeftOperand() = var.getAnAccess() and
ae.getRightOperand().getValue().toInt() > 0
)
@@ -128,14 +130,16 @@ where
exists(VariableAccess bound |
upperBoundCheck(loop, bound) and
reachesNoInc(bound, bound) and
msg = "The loop counter " + bound.getTarget().getName() +
msg =
"The loop counter " + bound.getTarget().getName() +
" is not always incremented in the loop body."
)
or
exists(VariableAccess bound |
lowerBoundCheck(loop, bound) and
reachesNoDec(bound, bound) and
msg = "The loop counter " + bound.getTarget().getName() +
msg =
"The loop counter " + bound.getTarget().getName() +
" is not always decremented in the loop body."
)
)

View File

@@ -21,6 +21,7 @@ where
if call.getTarget() = call.getEnclosingFunction()
then msg = "This call directly invokes its containing function $@."
else
msg = "The function " + call.getEnclosingFunction() +
msg =
"The function " + call.getEnclosingFunction() +
" is indirectly recursive via this call to $@."
select call, msg, call.getTarget(), call.getTarget().getName()

View File

@@ -17,7 +17,8 @@ predicate lockOrder(LockOperation outer, LockOperation inner) {
}
int orderCount(Declaration outerLock, Declaration innerLock) {
result = strictcount(LockOperation outer, LockOperation inner |
result =
strictcount(LockOperation outer, LockOperation inner |
outer.getLocked() = outerLock and
inner.getLocked() = innerLock and
lockOrder(outer, inner)
@@ -27,6 +28,6 @@ int orderCount(Declaration outerLock, Declaration innerLock) {
from LockOperation outer, LockOperation inner
where
lockOrder(outer, inner) and
orderCount(outer.getLocked(), inner.getLocked()) <= orderCount(inner.getLocked(),
outer.getLocked())
orderCount(outer.getLocked(), inner.getLocked()) <=
orderCount(inner.getLocked(), outer.getLocked())
select inner, "Out-of-order locks: A " + inner.say() + " usually precedes a $@.", outer, outer.say()

View File

@@ -81,10 +81,8 @@ class LockingPrimitive extends FunctionCall, LockOperation {
override Function getLocked() { result = this.getTarget() }
override UnlockOperation getMatchingUnlock() {
result.(UnlockingPrimitive).getTarget().getName() = this
.getTarget()
.getName()
.replaceAll("Lock", "Unlock")
result.(UnlockingPrimitive).getTarget().getName() =
this.getTarget().getName().replaceAll("Lock", "Unlock")
}
override string say() { result = "call to " + getLocked().getName() }

View File

@@ -29,7 +29,8 @@ where
numStmt(f, line) = cnt and
cnt > 1 and
o.onLine(f, line) and
o.getLocation().getStartColumn() = min(OneLineStmt other, int toMin |
o.getLocation().getStartColumn() =
min(OneLineStmt other, int toMin |
other.onLine(f, line) and toMin = other.getLocation().getStartColumn()
|
toMin

View File

@@ -14,7 +14,8 @@ import cpp
string var(Variable v) {
exists(int level | level = v.getType().getPointerIndirectionLevel() |
level > 2 and
result = "The type of " + v.getName() + " uses " + level +
result =
"The type of " + v.getName() + " uses " + level +
" levels of pointer indirection -- maximum allowed is 2."
)
}
@@ -22,7 +23,8 @@ string var(Variable v) {
string fun(Function f) {
exists(int level | level = f.getType().getPointerIndirectionLevel() |
level > 2 and
result = "The return type of " + f.getName() + " uses " + level +
result =
"The return type of " + f.getName() + " uses " + level +
" levels of pointer indirection -- maximum allowed is 2."
)
}

View File

@@ -12,7 +12,8 @@
import cpp
int firstCodeLine(File f) {
result = min(Declaration d, Location l, int toMin |
result =
min(Declaration d, Location l, int toMin |
(
l = d.getLocation() and
l.getFile() = f and

View File

@@ -59,7 +59,8 @@ Expr getMulOperand(MulExpr me) { result = me.getAnOperand() }
* ```
*/
int getEffectiveMulOperands(MulExpr me) {
result = count(Expr op |
result =
count(Expr op |
op = getMulOperand*(me) and
not op instanceof MulExpr and
not likelySmall(op)
@@ -109,24 +110,28 @@ class MulAnalyzableExpr extends AnalyzableExpr, MulExpr {
class AddAnalyzableExpr extends AnalyzableExpr, AddExpr {
override float maxValue() {
result = this.getLeftOperand().getFullyConverted().(AnalyzableExpr).maxValue() +
result =
this.getLeftOperand().getFullyConverted().(AnalyzableExpr).maxValue() +
this.getRightOperand().getFullyConverted().(AnalyzableExpr).maxValue()
}
override float minValue() {
result = this.getLeftOperand().getFullyConverted().(AnalyzableExpr).minValue() +
result =
this.getLeftOperand().getFullyConverted().(AnalyzableExpr).minValue() +
this.getRightOperand().getFullyConverted().(AnalyzableExpr).minValue()
}
}
class SubAnalyzableExpr extends AnalyzableExpr, SubExpr {
override float maxValue() {
result = this.getLeftOperand().getFullyConverted().(AnalyzableExpr).maxValue() -
result =
this.getLeftOperand().getFullyConverted().(AnalyzableExpr).maxValue() -
this.getRightOperand().getFullyConverted().(AnalyzableExpr).minValue()
}
override float minValue() {
result = this.getLeftOperand().getFullyConverted().(AnalyzableExpr).minValue() -
result =
this.getLeftOperand().getFullyConverted().(AnalyzableExpr).minValue() -
this.getRightOperand().getFullyConverted().(AnalyzableExpr).maxValue()
}
}

View File

@@ -52,10 +52,7 @@ predicate introducesNewField(Class derived, Class base) {
from DataFlow::PathNode source, DataFlow::PathNode sink, CastToPointerArithFlow cfg
where
cfg.hasFlowPath(source, sink) and
source.getNode().asExpr().getFullyConverted().getUnspecifiedType() = sink
.getNode()
.asExpr()
.getFullyConverted()
.getUnspecifiedType()
source.getNode().asExpr().getFullyConverted().getUnspecifiedType() =
sink.getNode().asExpr().getFullyConverted().getUnspecifiedType()
select sink, source, sink,
"Pointer arithmetic here may be done with the wrong type because of the cast $@.", source, "here"

View File

@@ -130,11 +130,8 @@ predicate trivialConversion(ExpectedType expected, Type actual) {
or
// allow a pointer to any integral type of the same size
// (this permits signedness changes)
expected.(PointerType).getBaseType().(IntegralType).getSize() = actual
.(PointerType)
.getBaseType()
.(IntegralType)
.getSize()
expected.(PointerType).getBaseType().(IntegralType).getSize() =
actual.(PointerType).getBaseType().(IntegralType).getSize()
or
expected = actual
)

View File

@@ -65,11 +65,8 @@ predicate functionDefinedInIfDefRecursive(Function f) {
* break encapsulation.
*/
predicate baseCall(FunctionCall call) {
call.getNameQualifier().getQualifyingElement() = call
.getEnclosingFunction()
.getDeclaringType()
.(Class)
.getABaseClass+()
call.getNameQualifier().getQualifyingElement() =
call.getEnclosingFunction().getDeclaringType().(Class).getABaseClass+()
}
from PureExprInVoidContext peivc, Locatable parent, Locatable info, string info_text, string tail

View File

@@ -35,7 +35,8 @@ predicate booleanLiteral(Literal l) {
string boolLiteralInLogicalOp(Literal literal) {
booleanLiteral(literal) and
literal.getParent() instanceof BinaryLogicalOperation and
result = "Literal value " + literal.getValueText() +
result =
"Literal value " + literal.getValueText() +
" is used in a logical expression; simplify or use a constant."
}

View File

@@ -40,7 +40,8 @@ where
l = v.log2().floor() and
if v = 2.pow(l)
then
msg = "Operand to short-circuiting operator looks like a flag (" + v + " = 2 ^ " + l +
msg =
"Operand to short-circuiting operator looks like a flag (" + v + " = 2 ^ " + l +
"), may be typo for bitwise operator."
else
exists(string kind |
@@ -49,7 +50,8 @@ where
or
e instanceof OctalLiteral and kind = "an octal literal"
) and
msg = "Operand to short-circuiting operator is " + kind +
msg =
"Operand to short-circuiting operator is " + kind +
", and therefore likely a flag; a bitwise operator may be intended."
)
select e, msg

View File

@@ -63,7 +63,8 @@ predicate isStringCopyUsedInLogicalOperationOrCondition(FunctionCall func, Expr
func = ce.getCondition()
)
) and
msg = "Return value of " + func.getTarget().getName() +
msg =
"Return value of " + func.getTarget().getName() +
" used directly in a conditional expression."
)
}

View File

@@ -111,17 +111,20 @@ predicate illDefinedForStmt(ForStmt for, string message) {
illDefinedForStmtWrongDirection(for, v, initialCondition, terminalCondition, isIncr) and
if for.conditionAlwaysFalse()
then
message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " +
message =
"Ill-defined for-loop: a loop using variable \"" + v + "\" counts " +
forLoopdirection(isIncr) + " from a value (" + initialCondition +
"), but the terminal condition is always false."
else
if for.conditionAlwaysTrue()
then
message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " +
message =
"Ill-defined for-loop: a loop using variable \"" + v + "\" counts " +
forLoopdirection(isIncr) + " from a value (" + initialCondition +
"), but the terminal condition is always true."
else
message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " +
message =
"Ill-defined for-loop: a loop using variable \"" + v + "\" counts " +
forLoopdirection(isIncr) + " from a value (" + initialCondition +
"), but the terminal condition is " + forLoopTerminalConditionRelationship(isIncr) +
" (" + terminalCondition + ")."

View File

@@ -30,9 +30,9 @@ class SprintfCall extends FunctionCall {
predicate isDangerous() { this.getMaxConvertedLength() > this.getBufferSize() }
string getDescription() {
result = "This conversion may yield a string of length " +
this.getMaxConvertedLength().toString() + ", which exceeds the allocated buffer size of " +
this.getBufferSize().toString()
result =
"This conversion may yield a string of length " + this.getMaxConvertedLength().toString() +
", which exceeds the allocated buffer size of " + this.getBufferSize().toString()
}
}

View File

@@ -28,7 +28,8 @@ class NullInstruction extends ConstantValueInstruction {
}
predicate explicitNullTestOfInstruction(Instruction checked, Instruction bool) {
bool = any(CompareInstruction cmp |
bool =
any(CompareInstruction cmp |
exists(NullInstruction null |
cmp.getLeft() = null and cmp.getRight() = checked
or
@@ -40,7 +41,8 @@ predicate explicitNullTestOfInstruction(Instruction checked, Instruction bool) {
)
)
or
bool = any(ConvertInstruction convert |
bool =
any(ConvertInstruction convert |
checked = convert.getUnary() and
convert.getResultType() instanceof BoolType and
checked.getResultType() instanceof PointerType

View File

@@ -17,7 +17,9 @@ where
hasSuperfluousConstReturn(f) and
if f.hasSpecifier("const") or f.isStatic()
then
message = "The 'const' modifier has no effect on return types. The 'const' modifying the return type can be removed."
message =
"The 'const' modifier has no effect on return types. The 'const' modifying the return type can be removed."
else
message = "The 'const' modifier has no effect on return types. For a const function, the 'const' should go after the parameter list."
message =
"The 'const' modifier has no effect on return types. For a const function, the 'const' should go after the parameter list."
select f, message

View File

@@ -14,6 +14,7 @@ import cpp
from Class c, int n
where
c.fromSource() and
n = c.getMetrics().getNumberOfMembers() +
n =
c.getMetrics().getNumberOfMembers() +
sum(Function f | c.getACanonicalMemberFunction() = f | f.getMetrics().getNumberOfLinesOfCode())
select c, n order by n desc

View File

@@ -15,16 +15,15 @@ import cpp
from Class c, int ccLoc, int loc
where
c.fromSource() and
ccLoc = sum(Function f |
ccLoc =
sum(Function f |
c.getACanonicalMemberFunction() = f and
f.getMetrics().getCyclomaticComplexity() > 18
|
f.getMetrics().getNumberOfLinesOfCode()
) and
loc = sum(Function f |
c.getACanonicalMemberFunction() = f
|
f.getMetrics().getNumberOfLinesOfCode()
) + c.getMetrics().getNumberOfMembers() and
loc =
sum(Function f | c.getACanonicalMemberFunction() = f | f.getMetrics().getNumberOfLinesOfCode()) +
c.getMetrics().getNumberOfMembers() and
loc != 0
select c, (ccLoc * 100).(float) / loc as n order by n desc

View File

@@ -76,7 +76,8 @@ class Library extends LibraryT {
* `sourceFile` is not in `destLib`).
*/
predicate libDependencies(File sourceFile, Library destLib, int num) {
num = strictcount(Element source, Element dest, File destFile |
num =
strictcount(Element source, Element dest, File destFile |
// dependency from source -> dest.
dependsOnSimple(source, dest) and
sourceFile = source.getFile() and
@@ -101,7 +102,7 @@ predicate libDependencies(File sourceFile, Library destLib, int num) {
predicate encodedDependencies(File source, string encodedDependency, int num) {
exists(Library destLib |
libDependencies(source, destLib, num) and
encodedDependency = "/" + source.getRelativePath() + "<|>" + destLib.getName() + "<|>" +
destLib.getVersion()
encodedDependency =
"/" + source.getRelativePath() + "<|>" + destLib.getName() + "<|>" + destLib.getVersion()
)
}

View File

@@ -85,7 +85,8 @@ private predicate closeWithDepth(int depth, File f, PreprocessorDirective close,
predicate length(PreprocessorDirective open, int length) {
exists(int depth, File f, int start, int end |
openWithDepth(depth, f, open, start) and
end = min(PreprocessorDirective endif, int closeLine |
end =
min(PreprocessorDirective endif, int closeLine |
closeWithDepth(depth, f, endif, closeLine) and
closeLine > start
|

View File

@@ -19,7 +19,8 @@ where
if loc > 0
then
// Weighted average of complexity by function length
complexity = sum(FunctionDeclarationEntry fde |
complexity =
sum(FunctionDeclarationEntry fde |
fde.getFile() = f
|
fde.getNumberOfLines() * fde.getCyclomaticComplexity()

View File

@@ -17,7 +17,8 @@ import external.CodeDuplication
from File f, int n
where
n = count(int line |
n =
count(int line |
exists(DuplicateBlock d | d.sourceFile() = f |
line in [d.sourceStartLine() .. d.sourceEndLine()]
) and

View File

@@ -15,7 +15,8 @@ import cpp
from File f, int n
where
f.fromSource() and
n = count(Comment c |
n =
count(Comment c |
c.getFile() = f and
(
c.getContents().matches("%TODO%") or

View File

@@ -20,7 +20,8 @@ predicate callToOperator(FunctionCall fc) {
from Function f, int n, int o
where
strictcount(f.getEntryPoint()) = 1 and
o = count(FunctionCall c |
o =
count(FunctionCall c |
c.getEnclosingFunction() = f and
not c.isInMacroExpansion() and
not c.isCompilerGenerated() and

View File

@@ -16,7 +16,8 @@ import external.VCS
from File f, int n
where
n = sum(Commit entry, int churn |
n =
sum(Commit entry, int churn |
churn = entry.getRecentChurnForFile(f) and
not artificialChange(entry)
|

View File

@@ -16,7 +16,8 @@ import external.VCS
from File f, int n
where
n = sum(Commit entry, int churn |
n =
sum(Commit entry, int churn |
churn = entry.getRecentAdditionsForFile(f) and
not artificialChange(entry)
|

View File

@@ -16,7 +16,8 @@ import external.VCS
from File f, int n
where
n = sum(Commit entry, int churn |
n =
sum(Commit entry, int churn |
churn = entry.getRecentDeletionsForFile(f) and
not artificialChange(entry)
|

View File

@@ -25,7 +25,8 @@ predicate inRange(Commit first, Commit second) {
}
int recommitsForFile(File f) {
result = count(Commit recommit |
result =
count(Commit recommit |
f = recommit.getAnAffectedFile() and
exists(Commit prev | inRange(prev, recommit))
)

View File

@@ -15,7 +15,8 @@ import external.VCS
from File f, int n
where
n = count(Commit e |
n =
count(Commit e |
e.getAnAffectedFile() = f and
e.daysToNow() <= 180 and
not artificialChange(e)

View File

@@ -147,7 +147,8 @@ library class SALElement extends Element {
exists(Location loc |
loc = this.(FunctionDeclarationEntry).getBlock().getLocation()
or
this = any(VariableDeclarationEntry vde |
this =
any(VariableDeclarationEntry vde |
vde.isDefinition() and
loc = vde.getVariable().getInitializer().getLocation()
)
@@ -194,7 +195,8 @@ private predicate salAnnotationPos(SALPosition pos) {
* ordering positions lexicographically by their start line and start column.
*/
private SALPosition salRelevantPositionAt(File file, int idx) {
result = rank[idx](SALPosition pos, int line, int col |
result =
rank[idx](SALPosition pos, int line, int col |
pos = MkSALPosition(file, line, col)
|
pos order by line, col

View File

@@ -21,6 +21,7 @@ where
if call.getTarget() = call.getEnclosingFunction()
then msg = "This call directly invokes its containing function $@."
else
msg = "The function " + call.getEnclosingFunction() +
msg =
"The function " + call.getEnclosingFunction() +
" is indirectly recursive via this call to $@."
select call, msg, call.getTarget(), call.getTarget().getName()

View File

@@ -58,7 +58,8 @@ VariableAccess getAnIncrement(Variable var) {
exists(AssignAddExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0)
or
exists(AssignExpr a | a.getLValue() = result |
a.getRValue() = any(AddExpr ae |
a.getRValue() =
any(AddExpr ae |
ae.getAnOperand() = var.getAnAccess() and
ae.getAnOperand().getValue().toInt() > 0
)
@@ -74,7 +75,8 @@ VariableAccess getADecrement(Variable var) {
exists(AssignSubExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0)
or
exists(AssignExpr a | a.getLValue() = result |
a.getRValue() = any(SubExpr ae |
a.getRValue() =
any(SubExpr ae |
ae.getLeftOperand() = var.getAnAccess() and
ae.getRightOperand().getValue().toInt() > 0
)
@@ -125,14 +127,16 @@ where
exists(VariableAccess bound |
upperBoundCheck(loop, bound) and
reachesNoInc(bound, bound) and
msg = "The loop counter " + bound.getTarget().getName() +
msg =
"The loop counter " + bound.getTarget().getName() +
" is not always incremented in the loop body."
)
or
exists(VariableAccess bound |
lowerBoundCheck(loop, bound) and
reachesNoDec(bound, bound) and
msg = "The loop counter " + bound.getTarget().getName() +
msg =
"The loop counter " + bound.getTarget().getName() +
" is not always decremented in the loop body."
)
)

View File

@@ -23,7 +23,8 @@ class MacroFunctionCall extends MacroInvocation {
}
int logicalLength(FunctionDeclarationEntry f) {
result = count(Stmt s |
result =
count(Stmt s |
s.getEnclosingFunction() = f.getFunction() and
s.getFile() = f.getFile() and
not s instanceof Block and

View File

@@ -39,7 +39,8 @@ where
numStmt(f, line) = cnt and
cnt > 1 and
o.onLine(f, line) and
o.getLocation().getStartColumn() = min(OneLineStmt other, int toMin |
o.getLocation().getStartColumn() =
min(OneLineStmt other, int toMin |
other.onLine(f, line) and toMin = other.getLocation().getStartColumn()
|
toMin

View File

@@ -23,7 +23,8 @@ class MacroFunctionCall extends MacroInvocation {
}
int logicalLength(FunctionDeclarationEntry f) {
result = count(Stmt s |
result =
count(Stmt s |
s.getEnclosingFunction() = f.getFunction() and
s.getFile() = f.getFile() and
not s instanceof Block and
@@ -34,7 +35,8 @@ int logicalLength(FunctionDeclarationEntry f) {
}
int assertionCount(FunctionDeclarationEntry f) {
result = count(Assertion a |
result =
count(Assertion a |
a.getAsserted().getEnclosingFunction() = f.getFunction() and a.getFile() = f.getFile()
)
}

View File

@@ -34,22 +34,24 @@ where
) and
if accessType = 1
then
message = "This '" + ba.getName() + "' operation accesses " +
plural(accessSize, " byte", " bytes") + " but the $@ is only " +
plural(bufferSize, " byte", " bytes") + "."
message =
"This '" + ba.getName() + "' operation accesses " + plural(accessSize, " byte", " bytes") +
" but the $@ is only " + plural(bufferSize, " byte", " bytes") + "."
else
if accessType = 2
then
message = "This '" + ba.getName() + "' operation may access " +
plural(accessSize, " byte", " bytes") + " but the $@ is only " +
plural(bufferSize, " byte", " bytes") + "."
message =
"This '" + ba.getName() + "' operation may access " + plural(accessSize, " byte", " bytes") +
" but the $@ is only " + plural(bufferSize, " byte", " bytes") + "."
else (
if accessSize > 0
then
message = "This array indexing operation accesses byte offset " + (accessSize - 1) +
message =
"This array indexing operation accesses byte offset " + (accessSize - 1) +
" but the $@ is only " + plural(bufferSize, " byte", " bytes") + "."
else
message = "This array indexing operation accesses a negative index " +
message =
"This array indexing operation accesses a negative index " +
((accessSize / ba.getActualType().getSize()) - 1) + " on the $@."
)
select ba, message, bufferAlloc, bufferDesc

View File

@@ -56,9 +56,12 @@ where
// very noisy on codebases that started as 32-bit
small.getExplicitlyConverted().getType().getSize() < 4 and
// Ignore cases where integer promotion has occurred on /, -, or >> expressions.
not getComparisonSize(large.(DivExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and
not getComparisonSize(large.(SubExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and
not getComparisonSize(large.(RShiftExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and
not getComparisonSize(large.(DivExpr).getLeftOperand().getExplicitlyConverted()) <=
getComparisonSize(small) and
not getComparisonSize(large.(SubExpr).getLeftOperand().getExplicitlyConverted()) <=
getComparisonSize(small) and
not getComparisonSize(large.(RShiftExpr).getLeftOperand().getExplicitlyConverted()) <=
getComparisonSize(small) and
// ignore loop-invariant smaller variables
loopVariant(small, l)
select rel,

View File

@@ -59,13 +59,15 @@ where
(
exists(BinaryLogicalOperation blop | blop.getAnOperand() = e1 |
e1.getType().(TypedefType).hasName("HRESULT") and
msg = "Usage of a type " + e1.getType().toString() +
msg =
"Usage of a type " + e1.getType().toString() +
" as an argument of a binary logical operation"
)
or
exists(UnaryLogicalOperation ulop | ulop.getAnOperand() = e1 |
e1.getType().(TypedefType).hasName("HRESULT") and
msg = "Usage of a type " + e1.getType().toString() +
msg =
"Usage of a type " + e1.getType().toString() +
" as an argument of a unary logical operation"
) and
not isHresultBooleanConverted(e1)

View File

@@ -108,7 +108,8 @@ where
exists(Expr source, Expr cmd, QuotedCommandInCreateProcessFunctionConfiguration quotedConfig |
cmd = call.getArgument(call.getCommandLineArgumentId()) and
quotedConfig.hasFlow(DataFlow2::exprNode(source), DataFlow2::exprNode(cmd)) and
msg2 = " and with an unquoted lpCommandLine (" + cmd +
msg2 =
" and with an unquoted lpCommandLine (" + cmd +
") introduces a security vulnerability if the path contains spaces."
)
select call, msg1 + " " + msg2

View File

@@ -90,9 +90,9 @@ class ParameterNullCheck extends ParameterCheck {
va = this.(NotExpr).getOperand() or
va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
va = getCheckedFalseCondition(this) or
va = any(NEExpr eq |
eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
).getAnOperand()
va =
any(NEExpr eq | eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0")
.getAnOperand()
)
or
nullSuccessor = getAFalseSuccessor() and
@@ -100,9 +100,9 @@ class ParameterNullCheck extends ParameterCheck {
(
va = this or
va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
va = any(EQExpr eq |
eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
).getAnOperand()
va =
any(EQExpr eq | eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0")
.getAnOperand()
)
)
}
@@ -188,7 +188,8 @@ class InitializationFunction extends Function {
isPointerDereferenceAssignmentTarget(this.getParameter(i).getAnAccess()) or
// Field wise assignment to the parameter
any(Assignment e).getLValue() = getAFieldAccess(this.getParameter(i)) or
i = this
i =
this
.(MemberFunction)
.getAnOverridingFunction+()
.(InitializationFunction)
@@ -231,7 +232,8 @@ class InitializationFunction extends Function {
)
)
or
result = any(AssumeExpr e |
result =
any(AssumeExpr e |
e.getEnclosingFunction() = this and e.getAChild().(Literal).getValue() = "0"
)
)
@@ -472,7 +474,8 @@ class ConditionalInitializationCall extends FunctionCall {
a.getLValue() = fa and
fa.getASuccessor+() = result
) and
result = this
result =
this
.getArgument(getTarget(this)
.(ConditionalInitializationFunction)
.conditionallyInitializedParameter(_))
@@ -589,7 +592,8 @@ Expr getAConditionallyInitializedArgument(
* Gets the type signature for the functions parameters.
*/
private string typeSig(Function f) {
result = concat(int i, Type pt |
result =
concat(int i, Type pt |
pt = f.getParameter(i).getType()
|
pt.getUnspecifiedType().toString(), "," order by i

View File

@@ -32,10 +32,12 @@ predicate setWorldWritable(FunctionCall fc, int mode) {
from Expr fc, int mode, string message
where
worldWritableCreation(fc, mode) and
message = "A file may be created here with mode " + octalFileMode(mode) +
message =
"A file may be created here with mode " + octalFileMode(mode) +
", which would make it world-writable."
or
setWorldWritable(fc, mode) and
message = "This sets a file's permissions to " + octalFileMode(mode) +
message =
"This sets a file's permissions to " + octalFileMode(mode) +
", which would make it world-writable."
select fc, message

View File

@@ -15,8 +15,8 @@ bindingset[mode]
string octalFileMode(int mode) {
if mode >= 0 and mode <= 4095
then
/* octal 07777 */ result = "0" + octalDigitOpt(mode, 3) + octalDigit(mode, 2) +
octalDigit(mode, 1) + octalDigit(mode, 0)
/* octal 07777 */ result =
"0" + octalDigitOpt(mode, 3) + octalDigit(mode, 2) + octalDigit(mode, 1) + octalDigit(mode, 0)
else result = "[non-standard mode: decimal " + mode + "]"
}
@@ -128,12 +128,8 @@ class OpenatCreationExpr extends FileCreationExpr {
}
private int fopenMode() {
result = s_irusr()
.bitOr(s_irgrp())
.bitOr(s_iroth())
.bitOr(s_iwusr())
.bitOr(s_iwgrp())
.bitOr(s_iwoth())
result =
s_irusr().bitOr(s_irgrp()).bitOr(s_iroth()).bitOr(s_iwusr()).bitOr(s_iwgrp()).bitOr(s_iwoth())
}
class FopenCreationExpr extends FileCreationExpr {

View File

@@ -52,9 +52,8 @@ class NonNullDaclConfig extends DataFlow2::Configuration {
NonNullDaclConfig() { this = "NonNullDaclConfig" }
override predicate isSource(DataFlow::Node source) {
source.getType().getUnspecifiedType().(PointerType).getBaseType() = any(Type t |
t.getName() = "ACL"
).getUnspecifiedType() and
source.getType().getUnspecifiedType().(PointerType).getBaseType() =
any(Type t | t.getName() = "ACL").getUnspecifiedType() and
(
// If the value comes from a function whose body we can't see, assume
// it's not null.
@@ -79,7 +78,8 @@ class NonNullDaclConfig extends DataFlow2::Configuration {
from SetSecurityDescriptorDaclFunctionCall call, string message
where
exists(NullValue nullExpr |
message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR will result in an unprotected object."
message =
"Setting a DACL to NULL in a SECURITY_DESCRIPTOR will result in an unprotected object."
|
call.getArgument(1).getValue().toInt() != 0 and
call.getArgument(2) = nullExpr
@@ -89,7 +89,8 @@ where
Expr constassign, VariableAccess var, NullDaclConfig nullDaclConfig,
NonNullDaclConfig nonNullDaclConfig
|
message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var +
message =
"Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var +
" that is set to NULL will result in an unprotected object."
|
var = call.getArgument(2) and

View File

@@ -73,7 +73,8 @@ FunctionDeclarationEntry sourceMethod() {
}
int numberOfSourceMethods(Class c) {
result = count(FunctionDeclarationEntry m |
result =
count(FunctionDeclarationEntry m |
m = sourceMethod() and
m.getFunction().getDeclaringType() = c
)
@@ -126,7 +127,8 @@ predicate similarLines(File f, int line) {
}
private predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) {
lines = strictsum(SimilarBlock b, int toSum |
lines =
strictsum(SimilarBlock b, int toSum |
(b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and
toSum = b.sourceLines()
|
@@ -137,7 +139,8 @@ private predicate similarLinesPerEquivalenceClass(int equivClass, int lines, Fil
private predicate similarLinesCoveredFiles(File f, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
exists(int coveredApprox |
coveredApprox = strictsum(int num |
coveredApprox =
strictsum(int num |
exists(int equivClass |
similarLinesPerEquivalenceClass(equivClass, num, f) and
similarLinesPerEquivalenceClass(equivClass, num, otherFile) and
@@ -153,7 +156,8 @@ predicate similarLinesCovered(File f, int coveredLines, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
similarLinesCoveredFiles(f, otherFile) and
exists(int notCovered |
notCovered = count(int j |
notCovered =
count(int j |
j in [1 .. numLines] and
not similarLines(f, j)
) and
@@ -169,7 +173,8 @@ predicate duplicateLines(File f, int line) {
}
private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) {
lines = strictsum(DuplicateBlock b, int toSum |
lines =
strictsum(DuplicateBlock b, int toSum |
(b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and
toSum = b.sourceLines()
|
@@ -180,7 +185,8 @@ private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, F
predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
exists(int coveredApprox |
coveredApprox = strictsum(int num |
coveredApprox =
strictsum(int num |
exists(int equivClass |
duplicateLinesPerEquivalenceClass(equivClass, num, f) and
duplicateLinesPerEquivalenceClass(equivClass, num, otherFile) and
@@ -190,7 +196,8 @@ predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) {
(coveredApprox * 100) / numLines > 75
) and
exists(int notCovered |
notCovered = count(int j |
notCovered =
count(int j |
j in [1 .. numLines] and
not duplicateLines(f, j)
) and
@@ -219,7 +226,8 @@ predicate duplicateFiles(File f, File other, int percent) {
}
predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total) {
numDup = strictcount(FunctionDeclarationEntry m1 |
numDup =
strictcount(FunctionDeclarationEntry m1 |
exists(FunctionDeclarationEntry m2 |
duplicateMethod(m1, m2) and
m1 = sourceMethod() and

View File

@@ -27,7 +27,8 @@ class DefectResult extends int {
string getMessage() { defectResults(this, _, _, _, _, _, _, result) }
string getURL() {
result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn()
+ ":" + getEndLine() + ":" + getEndColumn()
result =
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +
getEndLine() + ":" + getEndColumn()
}
}

View File

@@ -37,7 +37,8 @@ class MetricResult extends int {
float getValue() { metricResults(this, _, _, _, _, _, _, result) }
string getURL() {
result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn()
+ ":" + getEndLine() + ":" + getEndColumn()
result =
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +
getEndLine() + ":" + getEndColumn()
}
}

View File

@@ -73,13 +73,13 @@ string extraDetail(
else
if strictcount(possibleGuard(hf, _)) = 1
then
result = " (" + possibleGuard(hf, _) + " should appear in the #ifndef rather than " + s +
")."
result =
" (" + possibleGuard(hf, _) + " should appear in the #ifndef rather than " + s + ")."
else
if strictcount(possibleGuard(hf, "")) = 1
then
result = " (" + possibleGuard(hf, "") + " should appear in the #ifndef rather than " + s
+ ")."
result =
" (" + possibleGuard(hf, "") + " should appear in the #ifndef rather than " + s + ")."
else result = " (the macro " + s + " is checked for, but is not defined)."
)
}

View File

@@ -30,7 +30,8 @@ predicate canonicalName1(Declaration d, string canonical) {
}
predicate canonicalName2(Declaration d, string canonical) {
canonical = d
canonical =
d
.getName()
.replaceAll("_", "")
.replaceAll("0", "O")

View File

@@ -64,18 +64,22 @@ from ProperClass c, string msg
where
not definesDefaultConstructor(c) and
not c.hasConstructor() and
msg = "AV Rule 68: class " + c.getName() +
msg =
"AV Rule 68: class " + c.getName() +
" does not need a default constructor and should explicitly disallow it."
or
not definesCopyConstructor(c) and
msg = "AV Rule 68: class " + c.getName() +
msg =
"AV Rule 68: class " + c.getName() +
" does not need a copy constructor and should explicitly disallow it."
or
not definesCopyAssignmentOperator(c) and
msg = "AV Rule 68: class " + c.getName() +
msg =
"AV Rule 68: class " + c.getName() +
" does not need a copy assignment operator and should explicitly disallow it."
or
not definesDestructor(c) and
msg = "AV Rule 68: class " + c.getName() +
msg =
"AV Rule 68: class " + c.getName() +
" does not need a destructor and should explicitly disallow it."
select c, msg

View File

@@ -68,24 +68,24 @@ where
(
(
virtualThisCall(call, overridingFunction) and
explanation = "Call to virtual function $@ which is overridden in $@. If you intend to statically call this virtual function, it should be qualified with "
explanation =
"Call to virtual function $@ which is overridden in $@. If you intend to statically call this virtual function, it should be qualified with "
+ virtFunction.getDeclaringType().toString() + "::."
) and
virtFunction = call.getTarget() and
overridingFunction.getDeclaringType().getABaseClass+() = call
.getEnclosingFunction()
.getDeclaringType()
overridingFunction.getDeclaringType().getABaseClass+() =
call.getEnclosingFunction().getDeclaringType()
or
exists(VirtualFunction target |
thisCall(call) and indirectlyCallsVirtualFunction(call.getTarget(), target, _)
|
explanation = "Call to function " + call.getTarget().getName() +
explanation =
"Call to function " + call.getTarget().getName() +
" that calls virtual function $@ (overridden in $@)." and
virtFunction = target and
overridingFunction = target.getAnOverridingFunction() and
overridingFunction.getDeclaringType().getABaseClass+() = call
.getEnclosingFunction()
.getDeclaringType()
overridingFunction.getDeclaringType().getABaseClass+() =
call.getEnclosingFunction().getDeclaringType()
)
)
select call, explanation, virtFunction, virtFunction.getName(), overridingFunction,

View File

@@ -282,15 +282,16 @@ where
(
exists(Function releaseFunction, int releaseLine |
badRelease(r, acquire, releaseFunction, releaseLine) and
message = "Resource " + r.getName() + " is acquired by class " +
r.getDeclaringType().getName() +
message =
"Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() +
" but not released in the destructor. It is released from " + releaseFunction.getName() +
" on line " + releaseLine +
", so this function may need to be called from the destructor."
)
or
not badRelease(r, _, _, _) and
message = "Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() +
message =
"Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() +
" but not released anywhere in this class."
) and
not automaticallyReleased(acquire) and

View File

@@ -62,8 +62,8 @@ class ReferenceCopyAssignmentOperator extends MemberFunction {
/** A call to delete on a member variable */
DeleteExpr getADeleteExpr() {
result.getEnclosingFunction() = this and
result.getExpr().(VariableAccess).getTarget().(MemberVariable).getDeclaringType() = this
.getDeclaringType()
result.getExpr().(VariableAccess).getTarget().(MemberVariable).getDeclaringType() =
this.getDeclaringType()
}
}

View File

@@ -76,7 +76,8 @@ predicate assignOperatorWithWrongType(Operator op, string msg) {
exists(Class c |
c = op.getDeclaringType() and
op.getUnspecifiedType() = c and
msg = "Assignment operator in class " + c.getName() + " should have return type " + c.getName() +
msg =
"Assignment operator in class " + c.getName() + " should have return type " + c.getName() +
"&. Otherwise a copy is created at each call."
)
}
@@ -87,7 +88,8 @@ predicate assignOperatorWithWrongResult(Operator op, string msg) {
exists(op.getBlock()) and
not op.getType() instanceof VoidType and
not assignOperatorWithWrongType(op, _) and
msg = "Assignment operator in class " + op.getDeclaringType().getName() +
msg =
"Assignment operator in class " + op.getDeclaringType().getName() +
" does not return a reference to *this."
}

View File

@@ -45,13 +45,15 @@ class InterfaceImplementor extends Class {
}
int getNumInterfaces() {
result = count(ClassDerivation d |
result =
count(ClassDerivation d |
d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass
)
}
int getNumProtectedImplementations() {
result = count(ClassDerivation d |
result =
count(ClassDerivation d |
d.hasSpecifier("protected") and
d.getDerivedClass() = this and
not d.getBaseClass() instanceof InterfaceClass
@@ -59,7 +61,8 @@ class InterfaceImplementor extends Class {
}
int getNumPrivateImplementations() {
result = count(ClassDerivation d |
result =
count(ClassDerivation d |
d.hasSpecifier("private") and
d.getDerivedClass() = this and
not d.getBaseClass() instanceof InterfaceClass
@@ -67,7 +70,8 @@ class InterfaceImplementor extends Class {
}
int getNumPublicImplementations() {
result = count(ClassDerivation d |
result =
count(ClassDerivation d |
d.hasSpecifier("public") and
d.getDerivedClass() = this and
not d.getBaseClass() instanceof InterfaceClass

View File

@@ -14,7 +14,8 @@ import cpp
// Pick a representative file for a namespace - more than a bit dodgy, but otherwise
// the results don't show up anywhere which is less than helpful
predicate namespaceRepresentative(Namespace ns, File rep) {
rep.getAbsolutePath() = min(File f |
rep.getAbsolutePath() =
min(File f |
exists(Declaration d | d = ns.getADeclaration() | d.getFile() = f)
|
f.getAbsolutePath()

View File

@@ -58,6 +58,7 @@ where
reachable(blame) and
not functionImperfectlyExtracted(f) and
(blame = stmt or blame.(Expr).getEnclosingStmt() = stmt) and
msg = "Function " + f.getName() + " should return a value of type " + f.getType().getName() +
msg =
"Function " + f.getName() + " should return a value of type " + f.getType().getName() +
" but does not return a value here"
select stmt, msg

View File

@@ -19,12 +19,14 @@ predicate twoDeclarations(Declaration element, Location l1, Location l2) {
}
predicate twoDeclarationFilesWithDifferentNames(Declaration d, string f1, string f2) {
f1 = min(string s, File f, Location l |
f1 =
min(string s, File f, Location l |
twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName()
|
s
) and
f2 = min(string s, File f, Location l |
f2 =
min(string s, File f, Location l |
twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() and s != f1
|
s
@@ -32,12 +34,14 @@ predicate twoDeclarationFilesWithDifferentNames(Declaration d, string f1, string
}
predicate twoDeclarationFilesWithSameNames(Declaration d, string f1, string f2) {
f1 = min(string s, File f, Location l |
f1 =
min(string s, File f, Location l |
twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString()
|
s
) and
f2 = min(string s, File f, Location l |
f2 =
min(string s, File f, Location l |
twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() and s != f1
|
s

View File

@@ -53,8 +53,10 @@ class FloatUnion extends Union {
from Element e, string message
where
e instanceof InvalidFloatCastExpr and
message = "Casting a float pointer to another pointer type exposes the bit representation of the float, leading to unportable code."
message =
"Casting a float pointer to another pointer type exposes the bit representation of the float, leading to unportable code."
or
exists(FloatUnion fu | e = fu.getAFloatMember()) and
message = "Defining a union with a float member exposes the bit representation of the float, leading to unportable code."
message =
"Defining a union with a float member exposes the bit representation of the float, leading to unportable code."
select e, message

View File

@@ -18,12 +18,15 @@ import cpp
from Function o, string message
where
o.getName() = "operator&&" and
message = "AV Rule 159: the && operator shall not be overloaded as short-circuit semantics cannot be obtained."
message =
"AV Rule 159: the && operator shall not be overloaded as short-circuit semantics cannot be obtained."
or
o.getName() = "operator||" and
message = "AV Rule 159: the || operator shall not be overloaded as short-circuit semantics cannot be obtained."
message =
"AV Rule 159: the || operator shall not be overloaded as short-circuit semantics cannot be obtained."
or
o.getName() = "operator&" and
o.getNumberOfParameters() = 1 and
message = "AV Rule 159: the unary & operator shall not be overloaded because of undefined behavior."
message =
"AV Rule 159: the unary & operator shall not be overloaded because of undefined behavior."
select o, message

View File

@@ -61,7 +61,8 @@ predicate hasPragmaDifferentFile(File f) {
* us to skip past any preprocessor logic or similar code before the first comment.
*/
private int fileFirstComment(File f) {
result = min(int line |
result =
min(int line |
exists(Comment c |
c.getFile() = f and
c.getLocation().getStartLine() = line and
@@ -77,7 +78,8 @@ private int fileFirstComment(File f) {
private int fileHeaderLimit(File f) {
exists(int fc |
fc = fileFirstComment(f) and
result = min(int line |
result =
min(int line |
exists(DeclarationEntry de, Location l |
l = de.getLocation() and
l.getFile() = f and

View File

@@ -231,7 +231,8 @@ class Class extends UserType {
this = base and result = fieldInBase
or
exists(ClassDerivation cd | cd.getBaseClass() = base |
result = this
result =
this
.accessOfBaseMemberMulti(cd.getDerivedClass(),
fieldInBase.accessInDirectDerived(cd.getASpecifier().(AccessSpecifier)))
)
@@ -257,8 +258,8 @@ class Class extends UserType {
* includes the case of `base` = `this`.
*/
AccessSpecifier accessOfBaseMember(Declaration member) {
result = this
.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier))
result =
this.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier))
}
/**
@@ -962,9 +963,8 @@ abstract class ClassTemplateSpecialization extends Class {
result.getNamespace() = getNamespace() and
// It is distinguished by the fact that each of its template arguments
// is a distinct template parameter.
count(TemplateParameter tp | tp = result.getATemplateArgument()) = count(int i |
exists(result.getTemplateArgument(i))
)
count(TemplateParameter tp | tp = result.getATemplateArgument()) =
count(int i | exists(result.getTemplateArgument(i)))
}
override string getCanonicalQLClass() { result = "ClassTemplateSpecialization" }
@@ -1031,9 +1031,8 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization {
*/
exists(Type ta | ta = getATemplateArgument() and ta.involvesTemplateParameter()) and
count(TemplateParameter tp | tp = getATemplateArgument()) != count(int i |
exists(getTemplateArgument(i))
)
count(TemplateParameter tp | tp = getATemplateArgument()) !=
count(int i | exists(getTemplateArgument(i)))
}
override string getCanonicalQLClass() { result = "PartialClassTemplateSpecialization" }

View File

@@ -66,9 +66,8 @@ class Field extends MemberVariable {
final int getInitializationOrder() {
exists(Class cls, int memberIndex |
this = cls.getCanonicalMember(memberIndex) and
memberIndex = rank[result + 1](int index |
cls.getCanonicalMember(index).(Field).isInitializable()
)
memberIndex =
rank[result + 1](int index | cls.getCanonicalMember(index).(Field).isInitializable())
)
}
}

View File

@@ -45,7 +45,8 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
(
if exists(getATemplateArgument())
then
templateArgs = "<" +
templateArgs =
"<" +
concat(int i |
exists(getTemplateArgument(i))
|
@@ -53,7 +54,8 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
) + ">"
else templateArgs = ""
) and
args = "(" +
args =
"(" +
concat(int i |
exists(getParameter(i))
|
@@ -600,8 +602,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
result = getParameterDeclarationEntry(index).getTypedName()
or
index < getNumberOfParameters() - 1 and
result = getParameterDeclarationEntry(index).getTypedName() + ", " +
getParameterStringFrom(index + 1)
result =
getParameterDeclarationEntry(index).getTypedName() + ", " + getParameterStringFrom(index + 1)
}
/**

View File

@@ -163,5 +163,8 @@ class Parameter extends LocalScopeVariable, @parameter {
* An `int` that is a parameter index for some function. This is needed for binding in certain cases.
*/
class ParameterIndex extends int {
ParameterIndex() { exists(Parameter p | this = p.getIndex()) }
ParameterIndex() {
exists(Parameter p | this = p.getIndex()) or
exists(Call c | exists(c.getArgument(this))) // permit indexing varargs
}
}

View File

@@ -83,7 +83,8 @@ abstract class PreprocessorBranchDirective extends PreprocessorDirective {
* #ifdef or #ifndef.
*/
private int getIndexInBranch(PreprocessorBranch branch) {
this = rank[result](PreprocessorBranchDirective other |
this =
rank[result](PreprocessorBranchDirective other |
other.getIf() = branch
|
other order by other.getLocation().getStartLine()

View File

@@ -38,7 +38,8 @@ private string getParameterTypeString(Type parameterType) {
private string getTemplateArgumentString(Declaration d, int i) {
if exists(d.getTemplateArgumentKind(i))
then
result = d.getTemplateArgumentKind(i).(DumpType).getTypeIdentityString() + " " +
result =
d.getTemplateArgumentKind(i).(DumpType).getTypeIdentityString() + " " +
d.getTemplateArgument(i)
else result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString()
}
@@ -60,7 +61,8 @@ abstract private class DumpDeclaration extends Declaration {
final string getTemplateArgumentsString() {
if exists(this.getATemplateArgument())
then
result = "<" +
result =
"<" +
strictconcat(int i |
exists(this.getTemplateArgument(i))
|
@@ -87,7 +89,8 @@ private class DumpType extends Type {
// and `getDeclaratorSuffixBeforeQualifiers()`. To create the type identity
// for a `SpecifiedType`, insert the qualifiers after
// `getDeclaratorSuffixBeforeQualifiers()`.
result = getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() +
result =
getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() +
getDeclaratorSuffix()
}
@@ -219,7 +222,8 @@ private class ArrayDumpType extends DerivedDumpType, ArrayType {
override string getDeclaratorSuffixBeforeQualifiers() {
if exists(getArraySize())
then
result = "[" + getArraySize().toString() + "]" +
result =
"[" + getArraySize().toString() + "]" +
getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
else result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
}
@@ -263,7 +267,8 @@ private class RoutineDumpType extends DumpType, RoutineType {
language[monotonicAggregates]
override string getDeclaratorSuffixBeforeQualifiers() {
result = "(" +
result =
"(" +
concat(int i |
exists(getParameterType(i))
|
@@ -272,7 +277,8 @@ private class RoutineDumpType extends DumpType, RoutineType {
}
override string getDeclaratorSuffix() {
result = getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
result =
getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
getReturnType().(DumpType).getDeclaratorSuffix()
}
}
@@ -328,7 +334,8 @@ private class DumpVariable extends DumpDeclaration, Variable {
exists(DumpType type |
(this instanceof MemberVariable or this instanceof GlobalOrNamespaceVariable) and
type = this.getType() and
result = type.getTypeSpecifier() + type.getDeclaratorPrefix() + " " + getScopePrefix(this) +
result =
type.getTypeSpecifier() + type.getDeclaratorPrefix() + " " + getScopePrefix(this) +
this.getName() + this.getTemplateArgumentsString() +
type.getDeclaratorSuffixBeforeQualifiers() + type.getDeclaratorSuffix()
)
@@ -337,14 +344,16 @@ private class DumpVariable extends DumpDeclaration, Variable {
private class DumpFunction extends DumpDeclaration, Function {
override string getIdentityString() {
result = getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() +
" " + getScopePrefix(this) + getName() + getTemplateArgumentsString() +
result =
getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + " " +
getScopePrefix(this) + getName() + getTemplateArgumentsString() +
getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix()
}
language[monotonicAggregates]
private string getDeclaratorSuffixBeforeQualifiers() {
result = "(" +
result =
"(" +
concat(int i |
exists(getParameter(i).getType())
|
@@ -365,7 +374,8 @@ private class DumpFunction extends DumpDeclaration, Function {
}
private string getDeclaratorSuffix() {
result = getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
result =
getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
getType().(DumpType).getDeclaratorSuffix()
}
}

View File

@@ -22,7 +22,8 @@ private predicate shouldPrintFunction(Function func) {
bindingset[s]
private string escapeString(string s) {
result = s
result =
s
.replaceAll("\\", "\\\\")
.replaceAll("\n", "\\n")
.replaceAll("\r", "\\r")
@@ -448,7 +449,8 @@ class FunctionNode extends ASTNode {
}
private int getOrder() {
this = rank[result](FunctionNode node, Function function, string file, int line, int column |
this =
rank[result](FunctionNode node, Function function, string file, int line, int column |
node.getAST() = function and
locationSortKeys(function, file, line, column)
|

View File

@@ -1166,8 +1166,8 @@ class ArrayType extends DerivedType {
override string explain() {
if exists(this.getArraySize())
then
result = "array of " + this.getArraySize().toString() + " {" + this.getBaseType().explain() +
"}"
result =
"array of " + this.getArraySize().toString() + " {" + this.getBaseType().explain() + "}"
else result = "array of {" + this.getBaseType().explain() + "}"
}
@@ -1364,7 +1364,8 @@ class PointerToMemberType extends Type, @ptrtomember {
}
override string explain() {
result = "pointer to member of " + this.getClass().toString() + " with type {" +
result =
"pointer to member of " + this.getClass().toString() + " with type {" +
this.getBaseType().explain() + "}"
}
@@ -1400,7 +1401,8 @@ class RoutineType extends Type, @routinetype {
Type getReturnType() { routinetypes(underlyingElement(this), unresolveElement(result)) }
override string explain() {
result = "function returning {" + this.getReturnType().explain() + "} with arguments (" +
result =
"function returning {" + this.getReturnType().explain() + "} with arguments (" +
this.explainParameters(0) + ")"
}

View File

@@ -266,7 +266,8 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
then result = super.toString()
else
exists(string idx |
idx = ((getIndex() + 1).toString() + "th")
idx =
((getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st")
.replaceAll("2th", "2nd")
.replaceAll("3th", "3rd")

View File

@@ -100,11 +100,8 @@ class XMLParent extends @xmlparent {
* left to right, separated by a space.
*/
string allCharactersString() {
result = concat(string chars, int pos |
xmlChars(_, chars, this, pos, _, _)
|
chars, " " order by pos
)
result =
concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
}
/** Gets the text value contained in this XML parent. */

View File

@@ -91,12 +91,14 @@ int getBufferSize(Expr bufferExpr, Element why) {
exists(DataFlow::ExprNode bufferExprNode |
// dataflow (all sources must be the same size)
bufferExprNode = DataFlow::exprNode(bufferExpr) and
result = min(Expr def |
result =
min(Expr def |
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
|
getBufferSize(def, _)
) and
result = max(Expr def |
result =
max(Expr def |
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
|
getBufferSize(def, _)

View File

@@ -258,14 +258,7 @@ class FormatLiteral extends Literal {
* Gets the position in the string at which the nth conversion specifier
* starts.
*/
int getConvSpecOffset(int n) {
n = 0 and result = this.getFormat().indexOf("%", 0, 0)
or
n > 0 and
exists(int p |
n = p + 1 and result = this.getFormat().indexOf("%", 0, this.getConvSpecOffset(p) + 2)
)
}
int getConvSpecOffset(int n) { result = this.getFormat().indexOf("%", n, 0) }
/*
* Each of these predicates gets a regular expressions to match each individual
@@ -311,7 +304,8 @@ class FormatLiteral extends Literal {
// 6 - length
// 7 - conversion character
// NB: this matches "%%" with conversion character "%"
result = "(?s)(\\%(" + this.getParameterFieldRegexp() + ")(" + this.getFlagRegexp() + ")(" +
result =
"(?s)(\\%(" + this.getParameterFieldRegexp() + ")(" + this.getFlagRegexp() + ")(" +
this.getFieldWidthRegexp() + ")(" + this.getPrecRegexp() + ")(" + this.getLengthRegexp() +
")(" + this.getConvCharRegexp() + ")" + "|\\%\\%).*"
}
@@ -844,11 +838,8 @@ class FormatLiteral extends Literal {
*/
int getFormatArgumentIndexFor(int n, int mode) {
hasFormatArgumentIndexFor(n, mode) and
(3 * n) + mode = rank[result + 1](int n2, int mode2 |
hasFormatArgumentIndexFor(n2, mode2)
|
(3 * n2) + mode2
)
(3 * n) + mode =
rank[result + 1](int n2, int mode2 | hasFormatArgumentIndexFor(n2, mode2) | (3 * n2) + mode2)
}
/**
@@ -960,7 +951,8 @@ class FormatLiteral extends Literal {
) and
// e.g. -2^31 = "-2147483648"
exists(int sizeBits |
sizeBits = min(int bits |
sizeBits =
min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8
or
exists(IntegralType t |
@@ -977,7 +969,8 @@ class FormatLiteral extends Literal {
this.getConversionChar(n).toLowerCase() = "u" and
// e.g. 2^32 - 1 = "4294967295"
exists(int sizeBits |
sizeBits = min(int bits |
sizeBits =
min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8
or
exists(IntegralType t |
@@ -994,7 +987,8 @@ class FormatLiteral extends Literal {
this.getConversionChar(n).toLowerCase() = "x" and
// e.g. "12345678"
exists(int sizeBytes, int baseLen |
sizeBytes = min(int bytes |
sizeBytes =
min(int bytes |
bytes = getIntegralDisplayType(n).getSize()
or
exists(IntegralType t |
@@ -1021,7 +1015,8 @@ class FormatLiteral extends Literal {
this.getConversionChar(n).toLowerCase() = "o" and
// e.g. 2^32 - 1 = "37777777777"
exists(int sizeBits, int baseLen |
sizeBits = min(int bits |
sizeBits =
min(int bits |
bits = getIntegralDisplayType(n).getSize() * 8
or
exists(IntegralType t |
@@ -1037,7 +1032,8 @@ class FormatLiteral extends Literal {
)
or
this.getConversionChar(n).toLowerCase() = "s" and
len = min(int v |
len =
min(int v |
v = this.getPrecision(n) or
v = this.getUse().getFormatArgument(n).(AnalysedString).getMaxLength() - 1 // (don't count null terminator)
)
@@ -1070,7 +1066,8 @@ class FormatLiteral extends Literal {
if n = 0
then result = this.getFormat().substring(0, this.getConvSpecOffset(0))
else
result = this
result =
this
.getFormat()
.substring(this.getConvSpecOffset(n - 1) + this.getConvSpec(n - 1).length(),
this.getConvSpecOffset(n))
@@ -1086,7 +1083,8 @@ class FormatLiteral extends Literal {
(
if n > 0
then
result = this
result =
this
.getFormat()
.substring(this.getConvSpecOffset(n - 1) + this.getConvSpec(n - 1).length(),
this.getFormat().length())
@@ -1099,7 +1097,8 @@ class FormatLiteral extends Literal {
if n = this.getNumConvSpec()
then result = this.getConstantSuffix().length() + 1
else
result = this.getConstantPart(n).length() + this.getMaxConvertedLength(n) +
result =
this.getConstantPart(n).length() + this.getMaxConvertedLength(n) +
this.getMaxConvertedLengthAfter(n + 1)
}
@@ -1107,7 +1106,8 @@ class FormatLiteral extends Literal {
if n = this.getNumConvSpec()
then result = this.getConstantSuffix().length() + 1
else
result = this.getConstantPart(n).length() + this.getMaxConvertedLengthLimited(n) +
result =
this.getConstantPart(n).length() + this.getMaxConvertedLengthLimited(n) +
this.getMaxConvertedLengthAfterLimited(n + 1)
}

View File

@@ -195,7 +195,8 @@ class ScanfFormatLiteral extends Expr {
// 2 - maximum width
// 3 - length modifier
// 4 - conversion character
result = "(\\%(" + this.getMaxWidthRegexp() + ")(" + this.getLengthRegexp() + ")(" +
result =
"(\\%(" + this.getMaxWidthRegexp() + ")(" + this.getLengthRegexp() + ")(" +
this.getConvCharRegexp() + ")).*"
}

View File

@@ -39,7 +39,8 @@ class AnalysedString extends Expr {
int getMaxLength() {
// take the longest AnalysedString it's value could 'flow' from; however if even one doesn't
// return a value (this essentially means 'infinity') we can't return a value either.
result = max(AnalysedString expr, int toMax |
result =
max(AnalysedString expr, int toMax |
canValueFlow*(expr, this) and toMax = expr.(StringLiteral).getOriginalLength()
|
toMax

View File

@@ -7,7 +7,8 @@ import cpp
bindingset[input]
int parseOctal(string input) {
input.charAt(0) = "0" and
result = strictsum(int ix |
result =
strictsum(int ix |
ix in [0 .. input.length()]
|
8.pow(input.length() - (ix + 1)) * input.charAt(ix).toInt()

View File

@@ -368,7 +368,8 @@ predicate useOfVarActual(SemanticStackVariable v, VariableAccess use) {
*/
private predicate excludeReachesFunction(Function f) {
exists(int defOrUses |
defOrUses = count(Def def | def.(ControlFlowNode).getControlFlowScope() = f) +
defOrUses =
count(Def def | def.(ControlFlowNode).getControlFlowScope() = f) +
count(Use use | use.(ControlFlowNode).getControlFlowScope() = f) and
defOrUses >= 13000
)

View File

@@ -310,13 +310,15 @@ private Node getControlOrderChildSparse(Node n, int i) {
not result instanceof TypeName and
not isDeleteDestructorCall(n)
or
n = any(AssignExpr a |
n =
any(AssignExpr a |
i = 0 and result = a.getRValue()
or
i = 1 and result = a.getLValue()
)
or
n = any(Call c |
n =
any(Call c |
not isDeleteDestructorCall(c) and
(
result = c.getArgument(i)
@@ -329,7 +331,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
or
n = any(ConditionDeclExpr cd | i = 0 and result = cd.getInitializingExpr())
or
n = any(DeleteExpr del |
n =
any(DeleteExpr del |
i = 0 and result = del.getExpr()
or
i = 1 and result = del.getDestructorCall()
@@ -337,7 +340,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
i = 2 and result = del.getAllocatorCall()
)
or
n = any(DeleteArrayExpr del |
n =
any(DeleteArrayExpr del |
i = 0 and result = del.getExpr()
or
i = 1 and result = del.getDestructorCall()
@@ -345,7 +349,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
i = 2 and result = del.getAllocatorCall()
)
or
n = any(NewArrayExpr new |
n =
any(NewArrayExpr new |
// Extra arguments to a built-in allocator, such as alignment or pointer
// address, are found at child positions >= 3. Extra arguments to custom
// allocators are instead placed as subexpressions of `getAllocatorCall`.
@@ -362,7 +367,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
i = 3 and result = new.getInitializer()
)
or
n = any(NewExpr new |
n =
any(NewExpr new |
// Extra arguments to a built-in allocator, such as alignment or pointer
// address, are found at child positions >= 3. Extra arguments to custom
// allocators are instead placed as subexpressions of `getAllocatorCall`.
@@ -379,7 +385,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
or
// The extractor sometimes emits literals with no value for captures and
// routes control flow around them.
n = any(Expr e |
n =
any(Expr e |
e.getParent() instanceof LambdaExpression and
result = e.getChild(i) and
forall(Literal lit | result = lit | exists(lit.getValue()))
@@ -387,7 +394,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
or
n = any(StmtExpr e | i = 0 and result = e.getStmt())
or
n = any(Initializer init |
n =
any(Initializer init |
not skipInitializer(init) and
not exists(ConditionDeclExpr cd | result = cd.getInitializingExpr()) and
i = 0 and
@@ -407,7 +415,8 @@ private Node getControlOrderChildSparse(Node n, int i) {
not result instanceof VlaDeclStmt and
not result instanceof VlaDimensionStmt
or
n = any(DeclStmt s |
n =
any(DeclStmt s |
exists(LocalVariable var | var = s.getDeclaration(i) |
result = var.getInitializer() and
not skipInitializer(result)
@@ -464,7 +473,8 @@ private predicate inStaticInitializer(Expr e) {
* contiguous, and the first index is 0.
*/
private Node getControlOrderChildDense(Node n, int i) {
result = rank[i + 1](Node child, int childIdx |
result =
rank[i + 1](Node child, int childIdx |
child = getControlOrderChildSparse(n, childIdx)
|
child order by childIdx
@@ -547,7 +557,8 @@ private class Spec extends Pos {
* together instead.
*/
private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
scope = any(Block b |
scope =
any(Block b |
i = -1 and ni = b and spec.isAt()
or
if exists(getLastControlOrderChild(b))
@@ -571,7 +582,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
)
)
or
scope = any(ShortCircuitOperator op |
scope =
any(ShortCircuitOperator op |
i = -1 and ni = op and spec.isBefore()
or
i = 0 and ni = op and spec.isAt()
@@ -579,7 +591,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 1 and ni = op.getFirstChildNode() and spec.isBefore()
)
or
scope = any(ThrowExpr e |
scope =
any(ThrowExpr e |
i = -1 and ni = e and spec.isBefore()
or
i = 0 and ni = e.getExpr() and spec.isAround()
@@ -591,7 +604,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 3 and ni = e.(ExceptionSource).getExceptionTarget() and spec.isBefore()
)
or
scope = any(ReturnStmt ret |
scope =
any(ReturnStmt ret |
i = -1 and ni = ret and spec.isAt()
or
i = 0 and ni = ret.getExpr() and spec.isAround()
@@ -601,7 +615,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 2 and ni = ret.getEnclosingFunction() and spec.isAt()
)
or
scope = any(JumpStmt s |
scope =
any(JumpStmt s |
i = -1 and ni = s and spec.isAt()
or
i = 0 and ni = s and spec.isAroundDestructors()
@@ -609,7 +624,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 1 and ni = s.getTarget() and spec.isBefore()
)
or
scope = any(ForStmt s |
scope =
any(ForStmt s |
// ForStmt [-> init]
i = -1 and ni = s and spec.isAt()
or
@@ -647,7 +663,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
)
)
or
scope = any(RangeBasedForStmt for |
scope =
any(RangeBasedForStmt for |
i = -1 and ni = for and spec.isAt()
or
exists(DeclStmt s | s.getADeclaration() = for.getRangeVariable() |
@@ -680,7 +697,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 7 and ni = for.getCondition() and spec.isBefore()
)
or
scope = any(TryStmt s |
scope =
any(TryStmt s |
i = -1 and ni = s and spec.isAt()
or
i = 0 and ni = s.getStmt() and spec.isAround()
@@ -688,7 +706,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 1 and ni = s and spec.isAfter()
)
or
scope = any(MicrosoftTryExceptStmt s |
scope =
any(MicrosoftTryExceptStmt s |
i = -1 and ni = s and spec.isAt()
or
i = 0 and ni = s.getStmt() and spec.isAround()
@@ -708,7 +727,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 7 and ni = s.(ExceptionSource).getExceptionTarget() and spec.isBefore()
)
or
scope = any(SwitchStmt s |
scope =
any(SwitchStmt s |
i = -1 and ni = s and spec.isAt()
or
i = 0 and ni = s.getExpr() and spec.isAround()
@@ -735,7 +755,8 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
i = 6 and ni = s and spec.isAfter()
)
or
scope = any(ComputedGotoStmt s |
scope =
any(ComputedGotoStmt s |
i = -1 and ni = s and spec.isAt()
or
i = 0 and ni = s.getExpr() and spec.isBefore()
@@ -1034,13 +1055,15 @@ private class LogicalOrLikeExpr extends ShortCircuitOperator {
Expr right;
LogicalOrLikeExpr() {
this = any(LogicalOrExpr e |
this =
any(LogicalOrExpr e |
left = e.getLeftOperand() and
right = e.getRightOperand()
)
or
// GNU extension: the binary `? :` operator
this = any(ConditionalExpr e |
this =
any(ConditionalExpr e |
e.isTwoOperand() and
left = e.getCondition() and
right = e.getElse()
@@ -1059,14 +1082,16 @@ private class ConditionalLikeExpr extends ShortCircuitOperator {
Expr elseExpr;
ConditionalLikeExpr() {
this = any(ConditionalExpr e |
this =
any(ConditionalExpr e |
not e.isTwoOperand() and
condition = e.getCondition() and
thenExpr = e.getThen() and
elseExpr = e.getElse()
)
or
this = any(BuiltInChooseExpr e |
this =
any(BuiltInChooseExpr e |
condition = e.getChild(0) and
thenExpr = e.getChild(1) and
elseExpr = e.getChild(2)

View File

@@ -492,28 +492,28 @@ library class ExprEvaluator extends int {
)
or
exists(AddExpr req | req = val |
result = getValueInternal(e, req.getLeftOperand()) +
getValueInternal(e, req.getRightOperand())
result =
getValueInternal(e, req.getLeftOperand()) + getValueInternal(e, req.getRightOperand())
)
or
exists(SubExpr req | req = val |
result = getValueInternal(e, req.getLeftOperand()) -
getValueInternal(e, req.getRightOperand())
result =
getValueInternal(e, req.getLeftOperand()) - getValueInternal(e, req.getRightOperand())
)
or
exists(MulExpr req | req = val |
result = getValueInternal(e, req.getLeftOperand()) *
getValueInternal(e, req.getRightOperand())
result =
getValueInternal(e, req.getLeftOperand()) * getValueInternal(e, req.getRightOperand())
)
or
exists(RemExpr req | req = val |
result = getValueInternal(e, req.getLeftOperand()) %
getValueInternal(e, req.getRightOperand())
result =
getValueInternal(e, req.getLeftOperand()) % getValueInternal(e, req.getRightOperand())
)
or
exists(DivExpr req | req = val |
result = getValueInternal(e, req.getLeftOperand()) /
getValueInternal(e, req.getRightOperand())
result =
getValueInternal(e, req.getLeftOperand()) / getValueInternal(e, req.getRightOperand())
)
or
exists(AssignExpr req | req = val | result = getValueInternal(e, req.getRValue()))
@@ -531,12 +531,14 @@ library class ExprEvaluator extends int {
exists(Variable v |
interestingVariableAccess(e, va, v, true) and
// All assignments must have the same int value
result = min(Expr value |
result =
min(Expr value |
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
|
getValueInternalNonSubExpr(value)
) and
result = max(Expr value |
result =
max(Expr value |
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
|
getValueInternalNonSubExpr(value)
@@ -606,86 +608,91 @@ library class ExprEvaluator extends int {
or
exists(LTExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) < getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) <
getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) >= getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) >=
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(GTExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) > getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) >
getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) <= getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) <=
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(LEExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) <= getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) <=
getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) > getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) >
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(GEExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) >= getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) >=
getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) < getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) <
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(EQExpr req | req = val |
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) = getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) =
getValueInternalNonSubExpr(req.getRightOperand())
or
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) != getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) !=
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(NEExpr req | req = val |
result = 0 and
getValueInternalNonSubExpr(req.getLeftOperand()) = getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) =
getValueInternalNonSubExpr(req.getRightOperand())
or
result = 1 and
getValueInternalNonSubExpr(req.getLeftOperand()) != getValueInternalNonSubExpr(req
.getRightOperand())
getValueInternalNonSubExpr(req.getLeftOperand()) !=
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(AddExpr req | req = val |
result = getValueInternalNonSubExpr(req.getLeftOperand()) +
result =
getValueInternalNonSubExpr(req.getLeftOperand()) +
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(SubExpr req | req = val |
result = getValueInternalNonSubExpr(req.getLeftOperand()) -
result =
getValueInternalNonSubExpr(req.getLeftOperand()) -
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(MulExpr req | req = val |
result = getValueInternalNonSubExpr(req.getLeftOperand()) *
result =
getValueInternalNonSubExpr(req.getLeftOperand()) *
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(RemExpr req | req = val |
result = getValueInternalNonSubExpr(req.getLeftOperand()) %
result =
getValueInternalNonSubExpr(req.getLeftOperand()) %
getValueInternalNonSubExpr(req.getRightOperand())
)
or
exists(DivExpr req | req = val |
result = getValueInternalNonSubExpr(req.getLeftOperand()) /
result =
getValueInternalNonSubExpr(req.getLeftOperand()) /
getValueInternalNonSubExpr(req.getRightOperand())
)
or

View File

@@ -98,7 +98,8 @@ private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) {
}
private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) {
referenceOut = any(FunctionCall call |
referenceOut =
any(FunctionCall call |
stdIdentityFunction(call.getTarget()) and
referenceIn = call.getArgument(0).getFullyConverted()
)

View File

@@ -598,7 +598,8 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
// `ClassAggregateLiteral` (`{ capture1, ..., captureN }`).
toExpr.(LambdaExpression).getInitializer() = fromExpr
or
toExpr = any(Call call |
toExpr =
any(Call call |
exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel, int iIn |
call.getTarget() = f and
f.hasDataFlow(inModel, outModel) and

View File

@@ -753,13 +753,15 @@ module FlowVar_internal {
ControlFlowNode node, Variable v, VariableAccess va, Expr assignedExpr
) {
// Together, the two following cases cover `Assignment`
node = any(AssignExpr ae |
node =
any(AssignExpr ae |
va = ae.getLValue() and
v = va.getTarget() and
assignedExpr = ae.getRValue()
)
or
node = any(AssignOperation ao |
node =
any(AssignOperation ao |
va = ao.getLValue() and
v = va.getTarget() and
// Here and in the `PrefixCrementOperation` case, we say that the assigned
@@ -771,7 +773,8 @@ module FlowVar_internal {
or
// This case does not add further data flow paths, except if a
// `PrefixCrementOperation` is itself a source
node = any(CrementOperation op |
node =
any(CrementOperation op |
va = op.getOperand() and
v = va.getTarget() and
assignedExpr = op

View File

@@ -132,6 +132,9 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
// dest_ptr = strdup(tainted_ptr)
inModel.isParameterDeref(argInIndex) and
exprIn = call.getArgument(argInIndex)
or
inModel.isParameter(argInIndex) and
exprIn = call.getArgument(argInIndex)
)
)
or
@@ -173,6 +176,9 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
// memcpy(&dest_var, tainted_ptr, len)
inModel.isParameterDeref(argInIndex) and
exprIn = call.getArgument(argInIndex)
or
inModel.isParameter(argInIndex) and
exprIn = call.getArgument(argInIndex)
)
)
or

View File

@@ -890,12 +890,8 @@ class DeleteExpr extends Expr, @delete_expr {
* Gets the compile-time type of the object being deleted.
*/
Type getDeletedObjectType() {
result = getExpr()
.getFullyConverted()
.getType()
.stripTopLevelSpecifiers()
.(PointerType)
.getBaseType()
result =
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType()
}
/**
@@ -968,12 +964,8 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
* Gets the element type of the array being deleted.
*/
Type getDeletedElementType() {
result = getExpr()
.getFullyConverted()
.getType()
.stripTopLevelSpecifiers()
.(PointerType)
.getBaseType()
result =
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType()
}
/**

View File

@@ -159,7 +159,8 @@ predicate ifndefDirective(PreprocessorDirective ppd, string macro) {
or
ppd instanceof PreprocessorIf and
exists(string head | head = ppd.getHead() |
macro = head
macro =
head
.replaceAll("(", " ")
.replaceAll(")", "")
.replaceAll("\t", " ")

View File

@@ -21,7 +21,8 @@ private predicate addressConstantVariable(Variable v) {
* expression_.
*/
private predicate constantAddressLValue(Expr lvalue) {
lvalue.(VariableAccess).getTarget() = any(Variable v |
lvalue.(VariableAccess).getTarget() =
any(Variable v |
v.(Variable).isStatic()
or
v instanceof GlobalOrNamespaceVariable
@@ -118,7 +119,8 @@ private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) {
}
private predicate pointerToLvalueStep(Expr pointerIn, Expr lvalueOut) {
lvalueOut = any(ArrayExpr ae |
lvalueOut =
any(ArrayExpr ae |
pointerIn = ae.getArrayBase().getFullyConverted() and
hasConstantValue(ae.getArrayOffset().getFullyConverted())
)
@@ -152,7 +154,8 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
or
pointerIn.getConversion() = pointerOut.(ParenthesisExpr)
or
pointerOut = any(ConditionalExpr cond |
pointerOut =
any(ConditionalExpr cond |
cond.getCondition().getFullyConverted().getValue().toInt() != 0 and
pointerIn = cond.getThen().getFullyConverted()
or
@@ -162,7 +165,8 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
or
// The comma operator is allowed by C++17 but disallowed by C99. This
// disjunct is a compromise that's chosen for being easy to implement.
pointerOut = any(CommaExpr comma |
pointerOut =
any(CommaExpr comma |
hasConstantValue(comma.getLeftOperand()) and
pointerIn = comma.getRightOperand().getFullyConverted()
)

View File

@@ -4,6 +4,8 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.DataFlow2
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.interfaces.DataFlow
/**
* A predictable instruction is one where an external user can predict
@@ -19,31 +21,19 @@ private predicate predictableInstruction(Instruction instr) {
predictableInstruction(instr.(UnaryInstruction).getUnary())
}
private DataFlow::Node getNodeForSource(Expr source) {
isUserInput(source, _) and
(
result = DataFlow::exprNode(source)
or
result = DataFlow::definitionByReferenceNode(source)
)
}
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
override predicate isSource(DataFlow::Node source) {
exists(CallInstruction ci, WriteSideEffectInstruction wsei |
userInputArgument(ci.getConvertedResultExpression(), wsei.getIndex()) and
source.asInstruction() = wsei and
wsei.getPrimaryInstruction() = ci
)
or
userInputReturned(source.asExpr())
or
isUserInput(source.asExpr(), _)
or
source.asExpr() instanceof EnvironmentRead
or
source
.asInstruction()
.(LoadInstruction)
.getSourceAddress()
.(VariableAddressInstruction)
.getASTVariable()
.hasName("argv") and
source.asInstruction().getEnclosingFunction().hasGlobalName("main")
}
override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
override predicate isSink(DataFlow::Node sink) { any() }
@@ -57,7 +47,7 @@ private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
private class ToGlobalVarTaintTrackingCfg extends DataFlow::Configuration {
ToGlobalVarTaintTrackingCfg() { this = "GlobalVarTaintTrackingCfg" }
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) }
override predicate isSink(DataFlow::Node sink) {
exists(GlobalOrNamespaceVariable gv | writesVariable(sink.asInstruction(), gv))
@@ -133,7 +123,8 @@ private predicate nodeIsBarrier(DataFlow::Node node) {
private predicate instructionTaintStep(Instruction i1, Instruction i2) {
// Expressions computed from tainted data are also tainted
i2 = any(CallInstruction call |
i2 =
any(CallInstruction call |
isPureFunction(call.getStaticCallTarget().getName()) and
call.getAnArgument() = i1 and
forall(Instruction arg | arg = call.getAnArgument() | arg = i1 or predictableInstruction(arg)) and
@@ -147,6 +138,9 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
or
i2.(UnaryInstruction).getUnary() = i1
or
i2.(ChiInstruction).getPartial() = i1 and
not isChiForAllAliasedMemory(i2)
or
exists(BinaryInstruction bin |
bin = i2 and
predictableInstruction(i2.getAnOperand().getDef()) and
@@ -156,18 +150,126 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
// This is part of the translation of `a[i]`, where we want taint to flow
// from `a`.
i2.(PointerAddInstruction).getLeft() = i1
// TODO: robust Chi handling
//
// TODO: Flow from argument to return of known functions: Port missing parts
// of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
// libraries.
//
// TODO: Flow from input argument to output argument of known functions: Port
// missing parts of `copyValueBetweenArguments` to the `interfaces.Taint` and
// `interfaces.DataFlow` libraries and implement call side-effect nodes. This
// will help with the test for `ExecTainted.ql`. The test for
// `TaintedPath.ql` is more tricky because the output arg is a pointer
// addition expression.
or
// Until we have from through indirections across calls, we'll take flow out
// of the parameter and into its indirection.
exists(IRFunction f, Parameter parameter |
i1 = getInitializeParameter(f, parameter) and
i2 = getInitializeIndirection(f, parameter)
)
or
// Until we have flow through indirections across calls, we'll take flow out
// of the indirection and into the argument.
// When we get proper flow through indirections across calls, this code can be
// moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class.
exists(ReadSideEffectInstruction read |
read.getAnOperand().(SideEffectOperand).getAnyDef() = i1 and
read.getArgumentDef() = i2
)
or
// Flow from argument to return value
i2 =
any(CallInstruction call |
exists(int indexIn |
modelTaintToReturnValue(call.getStaticCallTarget(), indexIn) and
i1 = getACallArgumentOrIndirection(call, indexIn)
)
)
or
// Flow from input argument to output argument
// TODO: This won't work in practice as long as all aliased memory is tracked
// together in a single virtual variable.
// TODO: Will this work on the test for `TaintedPath.ql`, where the output arg
// is a pointer addition expression?
i2 =
any(WriteSideEffectInstruction outNode |
exists(CallInstruction call, int indexIn, int indexOut |
modelTaintToParameter(call.getStaticCallTarget(), indexIn, indexOut) and
i1 = getACallArgumentOrIndirection(call, indexIn) and
outNode.getIndex() = indexOut and
outNode.getPrimaryInstruction() = call
)
)
}
pragma[noinline]
private InitializeIndirectionInstruction getInitializeIndirection(IRFunction f, Parameter p) {
result.getParameter() = p and
result.getEnclosingIRFunction() = f
}
pragma[noinline]
private InitializeParameterInstruction getInitializeParameter(IRFunction f, Parameter p) {
result.getParameter() = p and
result.getEnclosingIRFunction() = f
}
/**
* Get an instruction that goes into argument `argumentIndex` of `call`. This
* can be either directly or through one pointer indirection.
*/
private Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) {
result = call.getPositionalArgument(argumentIndex)
or
exists(ReadSideEffectInstruction readSE |
// TODO: why are read side effect operands imprecise?
result = readSE.getSideEffectOperand().getAnyDef() and
readSE.getPrimaryInstruction() = call and
readSE.getIndex() = argumentIndex
)
}
private predicate modelTaintToParameter(Function f, int parameterIn, int parameterOut) {
exists(FunctionInput modelIn, FunctionOutput modelOut |
(
f.(DataFlowFunction).hasDataFlow(modelIn, modelOut)
or
f.(TaintFunction).hasTaintFlow(modelIn, modelOut)
) and
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
modelOut.isParameterDeref(parameterOut)
)
}
/**
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
* Taint shoud not pass through these instructions since they tend to mix up
* unrelated objects.
*/
private predicate isChiForAllAliasedMemory(Instruction instr) {
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
or
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
or
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInput())
}
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
// Taint flow from parameter to return value
exists(FunctionInput modelIn, FunctionOutput modelOut |
f.(TaintFunction).hasTaintFlow(modelIn, modelOut) and
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
(modelOut.isReturnValue() or modelOut.isReturnValueDeref())
)
or
// Data flow (not taint flow) to where the return value points. For the time
// being we will conflate pointers and objects in taint tracking.
exists(FunctionInput modelIn, FunctionOutput modelOut |
f.(DataFlowFunction).hasDataFlow(modelIn, modelOut) and
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
modelOut.isReturnValueDeref()
)
or
// Taint flow from one argument to another and data flow from an argument to a
// return value. This happens in functions like `strcat` and `memcpy`. We
// could model this flow in two separate steps, but that would add reverse
// flow from the write side-effect to the call instruction, which may not be
// desirable.
exists(int parameterMid, InParameter modelMid, OutReturnValue returnOut |
modelTaintToParameter(f, parameterIn, parameterMid) and
modelMid.isParameter(parameterMid) and
f.(DataFlowFunction).hasDataFlow(modelMid, returnOut)
)
}
private Element adjustedSink(DataFlow::Node sink) {
@@ -199,31 +301,11 @@ private Element adjustedSink(DataFlow::Node sink) {
// For compatibility, send flow into a `NotExpr` even if it's part of a
// short-circuiting condition and thus might get skipped.
result.(NotExpr).getOperand() = sink.asExpr()
or
// For compatibility, send flow from argument read side effects to their
// corresponding argument expression
exists(IndirectReadSideEffectInstruction read |
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
read.getArgumentDef().getUnconvertedResultExpression() = result
)
or
exists(BufferReadSideEffectInstruction read |
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
read.getArgumentDef().getUnconvertedResultExpression() = result
)
or
exists(SizedBufferReadSideEffectInstruction read |
read.getAnOperand().(SideEffectOperand).getAnyDef() = sink.asInstruction() and
read.getArgumentDef().getUnconvertedResultExpression() = result
)
}
predicate tainted(Expr source, Element tainted) {
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
cfg.hasFlow(DataFlow::exprNode(source), sink)
or
cfg.hasFlow(DataFlow::definitionByReferenceNode(source), sink)
|
cfg.hasFlow(getNodeForSource(source), sink) and
tainted = adjustedSink(sink)
)
}
@@ -236,7 +318,7 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
ToGlobalVarTaintTrackingCfg toCfg, FromGlobalVarTaintTrackingCfg fromCfg, DataFlow::Node store,
GlobalOrNamespaceVariable global, DataFlow::Node load, DataFlow::Node sink
|
toCfg.hasFlow(DataFlow::exprNode(source), store) and
toCfg.hasFlow(getNodeForSource(source), store) and
store
.asInstruction()
.(StoreInstruction)

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