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

Skip to content

Commit c545012

Browse files
committed
Merge branch 'rc/1.20' into merge-rc
2 parents 94e4bd8 + 242f8f2 commit c545012

127 files changed

Lines changed: 2812 additions & 659 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.20/analysis-csharp.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,13 @@
3030

3131
* The class `TrivialProperty` now includes library properties determined to be trivial using CIL analysis. This may increase the number of results for all queries that use data flow.
3232
* Taint-tracking steps have been added for the `Json.NET` package. This will improve results for queries that use taint-tracking.
33+
* Support has been added for EntityFrameworkCore, including
34+
- Stored data flow sources
35+
- Sinks for SQL expressions
36+
- Data flow through fields that are mapped to the database.
37+
* Support has been added for NHibernate-Core, including
38+
- Stored data flow sources
39+
- Sinks for SQL expressions
40+
- Data flow through fields that are mapped to the database.
3341

3442
## Changes to the autobuilder

change-notes/1.20/analysis-javascript.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
| **Query** | **Tags** | **Purpose** |
2626
|-----------------------------------------------|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
27+
| Arbitrary file write during archive extraction ("Zip Slip") (`js/zipslip`) | security, external/cwe/cwe-022 | Identifies extraction routines that allow arbitrary file overwrite vulnerabilities. Results are hidden on LGTM by default. |
2728
| Arrow method on Vue instance (`js/vue/arrow-method-on-vue-instance`) | reliability, frameworks/vue | Highlights arrow functions that are used as methods on Vue instances. Results are shown on LGTM by default.|
2829
| Cross-window communication with unrestricted target origin (`js/cross-window-information-leak`) | security, external/cwe/201, external/cwe/359 | Highlights code that sends potentially sensitive information to another window without restricting the receiver window's origin, indicating a possible violation of [CWE-201](https://cwe.mitre.org/data/definitions/201.html). Results are shown on LGTM by default. |
2930
| Double escaping or unescaping (`js/double-escaping`) | correctness, security, external/cwe/cwe-116 | Highlights potential double escaping or unescaping of special characters, indicating a possible violation of [CWE-116](https://cwe.mitre.org/data/definitions/116.html). Results are shown on LGTM by default. |
@@ -55,7 +56,7 @@
5556
| Useless assignment to property. | Fewer false-positive results | This rule now treats assignments with complex right-hand sides correctly. |
5657
| Unsafe dynamic method access | Fewer false-positive results | This rule no longer flags concatenated strings as unsafe method names. |
5758
| Unvalidated dynamic method call | More true-positive results | This rule now flags concatenated strings as unvalidated method names in more cases. |
58-
| Useless conditional | More true-positive results | This rule now flags additional uses of function call values. |
59+
| Useless conditional | More true-positive results | This rule now flags additional uses of function call values. |
5960

6061
## Changes to QL libraries
6162

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Name, Category
2+
ASP.NET, Web application framework
3+
ASP.NET Core, Web application framework
4+
ASP.NET Razor templates, Web application framework
5+
EntityFramework, Database ORM
6+
EntityFramework Core, Database ORM
7+
Json.NET, Serialization
8+
NHibernate, Database ORM
9+
WinForms, User interface

change-notes/1.20/support/framework-support.rst

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@ The QL libraries and queries in this version have been explicitly checked agains
1515
C# built-in support
1616
================================
1717

18-
* ASP.Net MVC framework
19-
* ASP.NET Web API
20-
* ASP.NET Web Forms
21-
* ASP.NET Core
22-
* ASP.NET Core MVC
23-
* ASP.Net Core Razor
24-
* Razor templates
25-
18+
.. csv-table::
19+
:file: csharp-frameworks.csv
20+
:header-rows: 1
21+
:class: fullWidthTable
22+
:widths: auto
2623

2724
COBOL built-in support
2825
===================================

cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
</overview>
1010
<recommendation>
11-
<p>Consider changing the surrounding expression to match the floating point type. If rounding is intended, explicitly round using a standard function such as `trunc`, `floor` or `round`.</p>
11+
<p>Consider changing the surrounding expression to match the floating point type. If rounding is intended, explicitly round using a standard function such as <code>trunc</code>, <code>floor</code> or <code>round</code>.</p>
1212

1313
</recommendation>
1414
<example><sample src="LossyFunctionResultCast.cpp" />

cpp/ql/src/Likely Bugs/Likely Typos/FutileParams.qhelp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
<p>A function is called with arguments despite having an empty parameter list. This may indicate
99
that the incorrect function is being called, or that the author misunderstood the function.</p>
1010

11-
<p>In C, a function declared with an empty parameter list `()` is considered to have an unknown
11+
<p>In C, a function declared with an empty parameter list <code>()</code> is considered to have an unknown
1212
parameter list, and therefore can be called with any set of arguments. To declare a function
13-
which takes no arguments, you must use `(void)` as the parameter list in any forward declarations.
13+
which takes no arguments, you must use <code>(void)</code> as the parameter list in any forward declarations.
1414
In C++, either style of declaration indicates that the function accepts no arguments.</p>
1515

1616
</overview>

cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.qhelp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ memory after the function has already returned will have undefined results. </p>
2222

2323

2424
</example>
25+
26+
<references>
27+
</references>
2528
</qhelp>

cpp/ql/src/filters/ImportAdditionalLibraries.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module IRDataFlow {
2222
import semmle.code.cpp.ir.dataflow.DataFlow2
2323
import semmle.code.cpp.ir.dataflow.DataFlow3
2424
import semmle.code.cpp.ir.dataflow.DataFlow4
25+
import semmle.code.cpp.ir.dataflow.TaintTracking
2526
}
2627

2728
import semmle.code.cpp.valuenumbering.HashCons

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,13 @@ class CallInstruction extends Instruction {
13101310
result = getAnOperand()
13111311
}
13121312

1313+
/**
1314+
* Gets the `Function` that the call targets, if this is statically known.
1315+
*/
1316+
final Function getStaticCallTarget() {
1317+
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
1318+
}
1319+
13131320
/**
13141321
* Gets all of the arguments of the call, including the `this` pointer, if any.
13151322
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll

Lines changed: 145 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import cpp
33
private import InputIR
44
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
55

6+
private import semmle.code.cpp.models.interfaces.Alias
7+
68
private class IntValue = Ints::IntValue;
79

810
/**
@@ -46,7 +48,7 @@ private IntValue getFieldBitOffset(Field field) {
4648
* not result in any address held in that operand from escaping beyond the
4749
* instruction.
4850
*/
49-
predicate operandIsConsumedWithoutEscaping(Operand operand) {
51+
private predicate operandIsConsumedWithoutEscaping(Operand operand) {
5052
// The source/destination address of a Load/Store does not escape (but the
5153
// loaded/stored value could).
5254
operand instanceof AddressOperand or
@@ -60,7 +62,18 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) {
6062
// Converting an address to a `bool` does not escape the address.
6163
instr.(ConvertInstruction).getResultType() instanceof BoolType
6264
)
63-
)
65+
) or
66+
// Some standard function arguments never escape
67+
isNeverEscapesArgument(operand)
68+
}
69+
70+
private predicate operandEscapesDomain(Operand operand) {
71+
not operandIsConsumedWithoutEscaping(operand) and
72+
not operandIsPropagated(operand, _) and
73+
not isArgumentForParameter(_, operand, _) and
74+
not isOnlyEscapesViaReturnArgument(operand) and
75+
not operand.getUseInstruction() instanceof ReturnValueInstruction and
76+
not operand instanceof PhiOperand
6477
}
6578

6679
/**
@@ -98,7 +111,7 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
98111
* `bitOffset`. If the address is propagated, but the offset is not known to be
99112
* a constant, then `bitOffset` is unknown.
100113
*/
101-
predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
114+
private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
102115
exists(Instruction instr |
103116
instr = operand.getUseInstruction() and
104117
(
@@ -134,50 +147,146 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
134147
// offset of the field.
135148
bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or
136149
// A copy propagates the source value.
137-
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
150+
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 or
151+
// Some functions are known to propagate an argument
152+
isAlwaysReturnedArgument(operand) and bitOffset = 0
138153
)
139154
)
140155
}
141156

142-
/**
143-
* Holds if any address held in operand number `tag` of instruction `instr`
144-
* escapes outside the domain of the analysis.
145-
*/
146-
predicate operandEscapes(Operand operand) {
147-
// Conservatively assume that the address escapes unless one of the following
148-
// holds:
149-
not (
150-
// The operand is used in a way that does not escape the instruction
151-
operandIsConsumedWithoutEscaping(operand) or
152-
// The address is propagated to the result of the instruction, but that
153-
// result does not itself escape.
154-
operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction())
157+
private predicate operandEscapesNonReturn(Operand operand) {
158+
// The address is propagated to the result of the instruction, and that result itself is returned
159+
operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction())
160+
or
161+
// The operand is used in a function call which returns it, and the return value is then returned
162+
exists(CallInstruction ci, Instruction init |
163+
isArgumentForParameter(ci, operand, init) and
164+
(
165+
resultMayReachReturn(init) and
166+
resultEscapesNonReturn(ci)
167+
or
168+
resultEscapesNonReturn(init)
169+
)
155170
)
171+
or
172+
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction())
173+
or
174+
operand instanceof PhiOperand and
175+
resultEscapesNonReturn(operand.getUseInstruction())
176+
or
177+
operandEscapesDomain(operand)
178+
}
179+
180+
private predicate operandMayReachReturn(Operand operand) {
181+
// The address is propagated to the result of the instruction, and that result itself is returned
182+
operandIsPropagated(operand, _) and
183+
resultMayReachReturn(operand.getUseInstruction())
184+
or
185+
// The operand is used in a function call which returns it, and the return value is then returned
186+
exists(CallInstruction ci, Instruction init |
187+
isArgumentForParameter(ci, operand, init) and
188+
resultMayReachReturn(init) and
189+
resultMayReachReturn(ci)
190+
)
191+
or
192+
// The address is returned
193+
operand.getUseInstruction() instanceof ReturnValueInstruction
194+
or
195+
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction())
196+
or
197+
operand instanceof PhiOperand and
198+
resultMayReachReturn(operand.getUseInstruction())
199+
}
200+
201+
private predicate operandReturned(Operand operand, IntValue bitOffset) {
202+
// The address is propagated to the result of the instruction, and that result itself is returned
203+
exists(IntValue bitOffset1, IntValue bitOffset2 |
204+
operandIsPropagated(operand, bitOffset1) and
205+
resultReturned(operand.getUseInstruction(), bitOffset2) and
206+
bitOffset = Ints::add(bitOffset1, bitOffset2)
207+
)
208+
or
209+
// The operand is used in a function call which returns it, and the return value is then returned
210+
exists(CallInstruction ci, Instruction init, IntValue bitOffset1, IntValue bitOffset2 |
211+
isArgumentForParameter(ci, operand, init) and
212+
resultReturned(init, bitOffset1) and
213+
resultReturned(ci, bitOffset2) and
214+
bitOffset = Ints::add(bitOffset1, bitOffset2)
215+
216+
)
217+
or
218+
// The address is returned
219+
operand.getUseInstruction() instanceof ReturnValueInstruction and
220+
bitOffset = 0
221+
or
222+
isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction(), _) and
223+
bitOffset = Ints::unknown()
224+
}
225+
226+
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
227+
exists(Function f |
228+
ci = operand.getUseInstruction() and
229+
f = ci.getStaticCallTarget() and
230+
(
231+
init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
232+
or
233+
init instanceof InitializeThisInstruction and
234+
init.getEnclosingFunction() = f and
235+
operand instanceof ThisArgumentOperand
236+
) and
237+
not f.isVirtual() and
238+
not f instanceof AliasFunction
239+
)
240+
}
241+
242+
private predicate isAlwaysReturnedArgument(Operand operand) {
243+
exists(AliasFunction f |
244+
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
245+
f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex())
246+
)
247+
}
248+
249+
private predicate isOnlyEscapesViaReturnArgument(Operand operand) {
250+
exists(AliasFunction f |
251+
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
252+
f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex())
253+
)
254+
}
255+
256+
private predicate isNeverEscapesArgument(Operand operand) {
257+
exists(AliasFunction f |
258+
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
259+
f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex())
260+
)
261+
}
262+
263+
private predicate resultReturned(Instruction instr, IntValue bitOffset) {
264+
operandReturned(instr.getAUse(), bitOffset)
265+
}
266+
267+
private predicate resultMayReachReturn(Instruction instr) {
268+
operandMayReachReturn(instr.getAUse())
156269
}
157270

158271
/**
159272
* Holds if any address held in the result of instruction `instr` escapes
160273
* outside the domain of the analysis.
161274
*/
162-
predicate resultEscapes(Instruction instr) {
275+
private predicate resultEscapesNonReturn(Instruction instr) {
163276
// The result escapes if it has at least one use that escapes.
164-
operandEscapes(instr.getAUse())
277+
operandEscapesNonReturn(instr.getAUse())
165278
}
166279

167280
/**
168281
* Holds if the address of the specified local variable or parameter escapes the
169282
* domain of the analysis.
170283
*/
171284
private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) {
172-
exists(FunctionIR funcIR |
173-
funcIR = var.getEnclosingFunctionIR() and
174-
// The variable's address escapes if the result of any
175-
// VariableAddressInstruction that computes the variable's address escapes.
176-
exists(VariableAddressInstruction instr |
177-
instr.getEnclosingFunctionIR() = funcIR and
178-
instr.getVariable() = var and
179-
resultEscapes(instr)
180-
)
285+
// The variable's address escapes if the result of any
286+
// VariableAddressInstruction that computes the variable's address escapes.
287+
exists(VariableAddressInstruction instr |
288+
instr.getVariable() = var and
289+
resultEscapesNonReturn(instr)
181290
)
182291
}
183292

@@ -207,7 +316,14 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset)
207316
// If an operand is propagated, then the result points to the same variable,
208317
// offset by the bit offset from the propagation.
209318
resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and
210-
operandIsPropagated(operand, propagatedBitOffset) and
319+
(
320+
operandIsPropagated(operand, propagatedBitOffset)
321+
or
322+
exists(CallInstruction ci, Instruction init |
323+
isArgumentForParameter(ci, operand, init) and
324+
resultReturned(init, propagatedBitOffset)
325+
)
326+
) and
211327
bitOffset = Ints::add(originalBitOffset, propagatedBitOffset)
212328
)
213329
}

0 commit comments

Comments
 (0)