Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3d359bc

Browse files
committed
Merge remote-tracking branch 'upstream/master' into taintedLength
2 parents 30f1bcf + e330d5a commit 3d359bc

80 files changed

Lines changed: 3605 additions & 1178 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

change-notes/1.23/analysis-csharp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ The following changes in version 1.23 affect C# analysis in all applications.
3636
picture of the partial flow paths from a given source. The feature is
3737
disabled by default and can be enabled for individual configurations by
3838
overriding `int explorationLimit()`.
39+
* `foreach` statements where the body is guaranteed to be executed at least once, such as `foreach (var x in new string[]{ "a", "b", "c" }) { ... }`, are now recognized by all analyses based on the control flow graph (such as SSA, data flow and taint tracking).
3940

4041
## Changes to autobuilder

change-notes/1.23/analysis-javascript.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313

1414
| **Query** | **Tags** | **Purpose** |
1515
|---------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
16+
| Unused index variable (`js/unused-index-variable`) | correctness | Highlights loops that iterate over an array, but do not use the index variable to access array elements, indicating a possible typo or logic error. |
1617

1718

1819
## Changes to existing queries
1920

2021
| **Query** | **Expected impact** | **Change** |
2122
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
23+
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. |
2224
| Client-side cross-site scripting (`js/xss`) | More results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized. |
2325
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. |
2426
| Prototype pollution (`js/prototype-pollution`) | More results | The query now highlights vulnerable uses of jQuery and Angular, and the results are shown on LGTM by default. |

config/identical-files.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
"TaintTracking::Configuration Java/C++/C#": [
3030
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
3131
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
32+
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
33+
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
3234
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
3335
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
3436
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",

cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,12 @@ private module PartialDefinitions {
113113
)
114114
)
115115
} or
116-
TExplicitCallQualifier(Expr qualifier, Call call) { qualifier = call.getQualifier() } or
116+
TExplicitCallQualifier(Expr qualifier) {
117+
exists(Call call |
118+
qualifier = call.getQualifier() and
119+
not call.getTarget().hasSpecifier("const")
120+
)
121+
} or
117122
TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) }
118123

119124
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
@@ -128,7 +133,7 @@ private module PartialDefinitions {
128133
PartialDefinition() {
129134
this = TExplicitFieldStoreQualifier(definedExpr, node)
130135
or
131-
this = TExplicitCallQualifier(definedExpr, _) and node = definedExpr
136+
this = TExplicitCallQualifier(definedExpr) and node = definedExpr
132137
or
133138
this = TReferenceArgument(definedExpr, node)
134139
}

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
*
1414
* To use global (interprocedural) data flow, extend the class
1515
* `DataFlow::Configuration` as documented on that class. To use local
16-
* (intraprocedural) data flow, invoke `DataFlow::localFlow` or
17-
* `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`.
16+
* (intraprocedural) data flow between expressions, call
17+
* `DataFlow::localExprFlow`. For more general cases of local data flow, call
18+
* `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type
19+
* `DataFlow::Node`.
1820
*/
1921

2022
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow2.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
77
* `DataFlow4::Configuration`.
88
*
9-
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
9+
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
1010
*/
1111

1212
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow3.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
77
* `DataFlow4::Configuration`.
88
*
9-
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
9+
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
1010
*/
1111

1212
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow4.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
77
* `DataFlow4::Configuration`.
88
*
9-
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
9+
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
1010
*/
1111

1212
import cpp
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import cpp
2+
import semmle.code.cpp.security.Security
3+
private import semmle.code.cpp.ir.dataflow.DataFlow
4+
private import semmle.code.cpp.ir.IR
5+
6+
/**
7+
* A predictable expression is one where an external user can predict
8+
* the value. For example, a literal in the source code is considered
9+
* predictable.
10+
*/
11+
// TODO: Change to use Instruction instead of Expr. Naive attempt breaks
12+
// TaintedAllocationSize qltest.
13+
private predicate predictable(Expr expr) {
14+
expr instanceof Literal
15+
or
16+
exists(BinaryOperation binop | binop = expr |
17+
predictable(binop.getLeftOperand()) and predictable(binop.getRightOperand())
18+
)
19+
or
20+
exists(UnaryOperation unop | unop = expr | predictable(unop.getOperand()))
21+
}
22+
23+
// TODO: remove when `predictable` has an `Instruction` parameter instead of `Expr`.
24+
private predicate predictableInstruction(Instruction instr) {
25+
exists(DataFlow::Node node |
26+
node.asInstruction() = instr and
27+
predictable(node.asExpr())
28+
)
29+
}
30+
31+
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
32+
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
33+
34+
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
35+
36+
override predicate isSink(DataFlow::Node sink) { any() }
37+
38+
override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
39+
instructionTaintStep(n1.asInstruction(), n2.asInstruction())
40+
}
41+
42+
override predicate isBarrier(DataFlow::Node node) {
43+
exists(Variable checkedVar |
44+
accessesVariable(node.asInstruction(), checkedVar) and
45+
hasUpperBoundsCheck(checkedVar)
46+
)
47+
}
48+
}
49+
50+
private predicate accessesVariable(CopyInstruction copy, Variable var) {
51+
exists(VariableAddressInstruction va |
52+
va.getVariable().getAST() = var
53+
|
54+
copy.(StoreInstruction).getDestinationAddress() = va
55+
or
56+
copy.(LoadInstruction).getSourceAddress() = va
57+
)
58+
}
59+
60+
/**
61+
* A variable that has any kind of upper-bound check anywhere in the program
62+
*/
63+
// TODO: This coarse overapproximation, ported from the old taint tracking
64+
// library, could be replaced with an actual semantic check that a particular
65+
// variable _access_ is guarded by an upper-bound check. We probably don't want
66+
// to do this right away since it could expose a lot of FPs that were
67+
// previously suppressed by this predicate by coincidence.
68+
private predicate hasUpperBoundsCheck(Variable var) {
69+
exists(RelationalOperation oper, VariableAccess access |
70+
oper.getLeftOperand() = access and
71+
access.getTarget() = var and
72+
// Comparing to 0 is not an upper bound check
73+
not oper.getRightOperand().getValue() = "0"
74+
)
75+
}
76+
77+
private predicate instructionTaintStep(Instruction i1, Instruction i2) {
78+
// Expressions computed from tainted data are also tainted
79+
i2 = any(CallInstruction call |
80+
isPureFunction(call.getStaticCallTarget().getName()) and
81+
call.getAnArgument() = i1 and
82+
forall(Instruction arg | arg = call.getAnArgument() | arg = i1 or predictableInstruction(arg)) and
83+
// flow through `strlen` tends to cause dubious results, if the length is
84+
// bounded.
85+
not call.getStaticCallTarget().getName() = "strlen"
86+
)
87+
or
88+
// Flow through pointer dereference
89+
i2.(LoadInstruction).getSourceAddress() = i1
90+
or
91+
i2.(UnaryInstruction).getUnary() = i1
92+
or
93+
exists(BinaryInstruction bin |
94+
bin = i2 and
95+
predictableInstruction(i2.getAnOperand().getDef()) and
96+
i1 = i2.getAnOperand().getDef()
97+
)
98+
// TODO: Check that we have flow from `a` to `a[i]`. It may work for constant
99+
// `i` because there is flow through `predictable` `BinaryInstruction` and
100+
// through `LoadInstruction`.
101+
//
102+
// TODO: Flow from argument to return of known functions: Port missing parts
103+
// of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
104+
// libraries.
105+
//
106+
// TODO: Flow from input argument to output argument of known functions: Port
107+
// missing parts of `copyValueBetweenArguments` to the `interfaces.Taint` and
108+
// `interfaces.DataFlow` libraries and implement call side-effect nodes. This
109+
// will help with the test for `ExecTainted.ql`. The test for
110+
// `TaintedPath.ql` is more tricky because the output arg is a pointer
111+
// addition expression.
112+
}
113+
114+
predicate tainted(Expr source, Element tainted) {
115+
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
116+
cfg.hasFlow(DataFlow::exprNode(source), sink)
117+
|
118+
// TODO: is it more appropriate to use asConvertedExpr here and avoid
119+
// `getConversion*`? Or will that cause us to miss some cases where there's
120+
// flow to a conversion (like a `ReferenceDereferenceExpr`) and we want to
121+
// pretend there was flow to the converted `Expr` for the sake of
122+
// compatibility.
123+
sink.asExpr().getConversion*() = tainted
124+
or
125+
// For compatibility, send flow from arguments to parameters, even for
126+
// functions with no body.
127+
exists(FunctionCall call, int i |
128+
sink.asExpr() = call.getArgument(i) and
129+
tainted = resolveCall(call).getParameter(i)
130+
)
131+
or
132+
// For compatibility, send flow into a `Variable` if there is flow to any
133+
// Load or Store of that variable.
134+
exists(CopyInstruction copy |
135+
copy.getSourceValue() = sink.asInstruction() and
136+
accessesVariable(copy, tainted) and
137+
not hasUpperBoundsCheck(tainted)
138+
)
139+
or
140+
// For compatibility, send flow into a `NotExpr` even if it's part of a
141+
// short-circuiting condition and thus might get skipped.
142+
tainted.(NotExpr).getOperand() = sink.asExpr()
143+
)
144+
}
145+
146+
predicate taintedIncludingGlobalVars(Expr source, Element tainted, string globalVar) {
147+
tainted(source, tainted) and
148+
// TODO: Find a way to emulate how `security.TaintTracking` reports the last
149+
// global variable that taint has passed through. Also make sure we emulate
150+
// its behavior for interprocedural flow through globals.
151+
globalVar = ""
152+
}
153+
154+
GlobalOrNamespaceVariable globalVarFromId(string id) {
155+
// TODO: Implement this when `taintedIncludingGlobalVars` has support for
156+
// global variables.
157+
none()
158+
}
159+
160+
Function resolveCall(Call call) {
161+
// TODO: improve virtual dispatch. This will help in the test for
162+
// `UncontrolledProcessOperation.ql`.
163+
result = call.getTarget()
164+
}

0 commit comments

Comments
 (0)