mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Merge branch 'master' into connect-ir-dataflow-models
This commit is contained in:
@@ -26,6 +26,10 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The data-flow library has been improved when flow through functions needs to be
|
||||
combined with both taint tracking and flow through fields allowing more flow
|
||||
to be tracked. This affects and improves some security queries, which may
|
||||
report additional results.
|
||||
* Created the `semmle.code.cpp.models.interfaces.Allocation` library to model allocation such as `new` expressions and calls to `malloc`. This in intended to replace the functionality in `semmle.code.cpp.commons.Alloc` with a more consistent and useful interface.
|
||||
* Created the `semmle.code.cpp.models.interfaces.Deallocation` library to model deallocation such as `delete` expressions and calls to `free`. This in intended to replace the functionality in `semmle.code.cpp.commons.Alloc` with a more consistent and useful interface.
|
||||
* The new class `StackVariable` should be used in place of `LocalScopeVariable`
|
||||
@@ -40,4 +44,4 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
|
||||
* The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had
|
||||
the following improvements:
|
||||
* The library now models data flow through `strdup` and similar functions.
|
||||
|
||||
* The library now models data flow through formatting functions such as `sprintf`.
|
||||
|
||||
@@ -6,8 +6,12 @@ The following changes in version 1.24 affect C# analysis in all applications.
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| Assembly path injection (`cs/assembly-path-injection`) | security, external/cwe/cwe-114 | Finds user-controlled data used to load an assembly. |
|
||||
| Insecure configuration for ASP.NET requestValidationMode (`cs/insecure-request-validation-mode`) | security, external/cwe/cwe-016 | Finds where this attribute has been set to a value less than 4.5, which turns off some validation features and makes the application less secure. |
|
||||
| Page request validation is disabled (`cs/web/request-validation-disabled`) | security, frameworks/asp.net, external/cwe/cwe-016 | Finds where ASP.NET page request validation has been disabled, which could makes the application less secure. |
|
||||
| Insecure SQL connection (`cs/insecure-sql-connection`) | security, external/cwe/cwe-327 | Finds unencrypted SQL connection strings. |
|
||||
| Page request validation is disabled (`cs/web/request-validation-disabled`) | security, frameworks/asp.net, external/cwe/cwe-016 | Finds where ASP.NET page request validation has been disabled, which could make the application less secure. |
|
||||
| Serialization check bypass (`cs/serialization-check-bypass`) | security, external/cwe/cwe-20 | Finds where data is not validated in a deserialization method. |
|
||||
| XML injection (`cs/xml-injection`) | security, external/cwe/cwe-091 | Finds user-controlled data that is used to write directly to an XML document. |
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
@@ -25,9 +29,12 @@ The following changes in version 1.24 affect C# analysis in all applications.
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The data-flow library has been improved when flow through methods needs to be
|
||||
combined with both taint tracking and flow through fields allowing more flow
|
||||
to be tracked. This affects and improves most security queries, which may
|
||||
report additional results.
|
||||
* The taint tracking library now tracks flow through (implicit or explicit) conversion operator calls.
|
||||
* [Code contracts](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts) are now recognized, and are treated like any other assertion methods.
|
||||
* Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`.
|
||||
|
||||
## Changes to autobuilder
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ The following changes in version 1.24 affect Java analysis in all applications.
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| Disabled Spring CSRF protection (`java/spring-disabled-csrf-protection`) | security, external/cwe/cwe-352 | Finds disabled Cross-Site Request Forgery (CSRF) protection in Spring. |
|
||||
| Failure to use HTTPS or SFTP URL in Maven artifact upload/download (`java/maven/non-https-url`) | security, external/cwe/cwe-300, external/cwe/cwe-319, external/cwe/cwe-494, external/cwe/cwe-829 | Finds use of insecure protocols during Maven dependency resolution. Results are shown on LGTM by default. |
|
||||
| Left shift by more than the type width (`java/lshift-larger-than-type-width`) | correctness | Finds left shifts of ints by 32 bits or more and left shifts of longs by 64 bits or more. Results are shown on LGTM by default. |
|
||||
| Suspicious date format (`java/suspicious-date-format`) | correctness | Finds date format patterns that use placeholders that are likely to be incorrect. |
|
||||
|
||||
## Changes to existing queries
|
||||
@@ -18,11 +20,15 @@ The following changes in version 1.24 affect Java analysis in all applications.
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
| Dereferenced variable may be null (`java/dereferenced-value-may-be-null`) | Fewer false positives | Final fields with a non-null initializer are no longer reported. |
|
||||
| Expression always evaluates to the same value (`java/evaluation-to-constant`) | Fewer false positives | Expressions of the form `0 * x` are usually intended and no longer reported. |
|
||||
| Expression always evaluates to the same value (`java/evaluation-to-constant`) | Fewer false positives | Expressions of the form `0 * x` are usually intended and no longer reported. Also left shift of ints by 32 bits and longs by 64 bits are no longer reported as they are not constant, these results are instead reported by the new query `java/lshift-larger-than-type-width`. |
|
||||
| Useless null check (`java/useless-null-check`) | More true positives | Useless checks on final fields with a non-null initializer are now reported. |
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The data-flow library has been improved when flow through methods needs to be
|
||||
combined with both taint tracking and flow through fields allowing more flow
|
||||
to be tracked. This affects and improves most security queries, which may
|
||||
report additional results.
|
||||
* Identification of test classes has been improved. Previously, one of the
|
||||
match conditions would classify any class with a name containing the string
|
||||
"Test" as a test class, but now this matching has been replaced with one that
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
| Unbound event handler receiver (`js/unbound-event-handler-receiver`) | Fewer false positive results | This query now recognizes additional ways event handler receivers can be bound. |
|
||||
| Expression has no effect (`js/useless-expression`) | Fewer false positive results | The query now recognizes block-level flow type annotations and ignores the first statement of a try block. |
|
||||
| Use of call stack introspection in strict mode (`js/strict-mode-call-stack-introspection`) | Fewer false positive results | The query no longer flags expression statements. |
|
||||
| Missing CSRF middleware (`js/missing-token-validation`) | Fewer false positive results | The query reports fewer duplicates and only flags handlers that explicitly access cookie data. |
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
|
||||
@@ -82,6 +82,14 @@
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll"
|
||||
],
|
||||
"IR IRConfiguration": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/IRConfiguration.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/IRConfiguration.qll"
|
||||
],
|
||||
"IR UseSoundEscapeAnalysis": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/UseSoundEscapeAnalysis.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/UseSoundEscapeAnalysis.qll"
|
||||
],
|
||||
"IR Operand Tag": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/internal/OperandTag.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/internal/OperandTag.qll"
|
||||
@@ -182,9 +190,14 @@
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll"
|
||||
],
|
||||
"C++ SSA AliasAnalysis": [
|
||||
"SSA AliasAnalysis": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll"
|
||||
],
|
||||
"C++ SSA AliasAnalysisImports": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysisImports.qll"
|
||||
],
|
||||
"C++ IR ValueNumberingImports": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
|
||||
@@ -195,6 +208,10 @@
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll"
|
||||
],
|
||||
"IR AliasConfiguration (unaliased_ssa)": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll"
|
||||
],
|
||||
"IR SSA SSAConstruction": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll",
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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() + "%"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 + ")."
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
|
||||
|
||||
@@ -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)
|
||||
|
|
||||
|
||||
@@ -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)
|
||||
|
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
24
cpp/ql/src/external/CodeDuplication.qll
vendored
24
cpp/ql/src/external/CodeDuplication.qll
vendored
@@ -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
|
||||
|
||||
5
cpp/ql/src/external/DefectFilter.qll
vendored
5
cpp/ql/src/external/DefectFilter.qll
vendored
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
5
cpp/ql/src/external/MetricFilter.qll
vendored
5
cpp/ql/src/external/MetricFilter.qll
vendored
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
|
||||
|
||||
@@ -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) + ")"
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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, _)
|
||||
|
||||
@@ -311,7 +311,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 +845,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 +958,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 +976,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 +994,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 +1022,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 +1039,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 +1073,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 +1090,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 +1104,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 +1113,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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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() + ")).*"
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user