Skip to content

Commit 6249446

Browse files
author
Dave Bartolomeo
committed
Merge remote-tracking branch 'upstream/master' into dbartol/Indirections
2 parents 46c414b + 37570c7 commit 6249446

File tree

38 files changed

+605
-65
lines changed

38 files changed

+605
-65
lines changed

change-notes/1.24/analysis-cpp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
4040
* The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had
4141
the following improvements:
4242
* The library now models data flow through `strdup` and similar functions.
43-
43+
* The library now models data flow through formatting functions such as `sprintf`.

change-notes/1.24/analysis-csharp.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ The following changes in version 1.24 affect C# analysis in all applications.
66

77
| **Query** | **Tags** | **Purpose** |
88
|-----------------------------|-----------|--------------------------------------------------------------------|
9+
| Assembly path injection (`cs/assembly-path-injection`) | security, external/cwe/cwe-114 | Finds user-controlled data used to load an assembly. |
910
| 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. |
10-
| 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. |
11+
| Insecure SQL connection (`cs/insecure-sql-connection`) | security, external/cwe/cwe-327 | Finds unencrypted SQL connection strings. |
12+
| 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. |
13+
| Serialization check bypass (`cs/serialization-check-bypass`) | security, external/cwe/cwe-20 | Finds where data is not validated in a deserialization method. |
14+
| XML injection (`cs/xml-injection`) | security, external/cwe/cwe-091 | Finds user-controlled data that is used to write directly to an XML document. |
1115

1216
## Changes to existing queries
1317

@@ -30,4 +34,3 @@ The following changes in version 1.24 affect C# analysis in all applications.
3034
* Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`.
3135

3236
## Changes to autobuilder
33-

change-notes/1.24/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
| 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. |
3939
| 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. |
4040
| 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. |
41+
| 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. |
4142

4243
## Changes to libraries
4344

cpp/ql/src/Critical/DescriptorNeverClosed.qhelp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
<overview>
88
<p>
9-
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.
9+
This rule finds calls to <code>socket</code> where there is no corresponding <code>close</code> call in the program analyzed.
1010
Leaving descriptors open will cause a resource leak that will persist even after the program terminates.
1111
</p>
1212

1313
<include src="aliasAnalysisWarning.qhelp" />
1414
</overview>
1515

1616
<recommendation>
17-
<p>Ensure that all file or socket descriptors allocated by the program are freed before it terminates.</p>
17+
<p>Ensure that all socket descriptors allocated by the program are freed before it terminates.</p>
1818
</recommendation>
1919

2020
<example>

cpp/ql/src/Critical/DescriptorNeverClosed.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @name Open descriptor never closed
3-
* @description Functions that always return before closing the socket or file they opened leak resources.
3+
* @description Functions that always return before closing the socket they opened leak resources.
44
* @kind problem
55
* @id cpp/descriptor-never-closed
66
* @problem.severity warning

cpp/ql/src/semmle/code/cpp/Parameter.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,8 @@ class Parameter extends LocalScopeVariable, @parameter {
163163
* An `int` that is a parameter index for some function. This is needed for binding in certain cases.
164164
*/
165165
class ParameterIndex extends int {
166-
ParameterIndex() { exists(Parameter p | this = p.getIndex()) }
166+
ParameterIndex() {
167+
exists(Parameter p | this = p.getIndex()) or
168+
exists(Call c | exists(c.getArgument(this))) // permit indexing varargs
169+
}
167170
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
149149
or
150150
i2.(UnaryInstruction).getUnary() = i1
151151
or
152+
i2.(ChiInstruction).getPartial() = i1 and
153+
not isChiForAllAliasedMemory(i2)
154+
or
152155
exists(BinaryInstruction bin |
153156
bin = i2 and
154157
predictableInstruction(i2.getAnOperand().getDef()) and
@@ -199,12 +202,29 @@ private Instruction getACallArgumentOrIndirection(CallInstruction call, int argu
199202

200203
private predicate modelTaintToParameter(Function f, int parameterIn, int parameterOut) {
201204
exists(FunctionInput modelIn, FunctionOutput modelOut |
202-
f.(TaintFunction).hasTaintFlow(modelIn, modelOut) and
205+
(
206+
f.(DataFlowFunction).hasDataFlow(modelIn, modelOut)
207+
or
208+
f.(TaintFunction).hasTaintFlow(modelIn, modelOut)
209+
) and
203210
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
204211
modelOut.isParameterDeref(parameterOut)
205212
)
206213
}
207214

215+
/**
216+
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
217+
* Taint shoud not pass through these instructions since they tend to mix up
218+
* unrelated objects.
219+
*/
220+
private predicate isChiForAllAliasedMemory(Instruction instr) {
221+
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
222+
or
223+
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
224+
or
225+
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInput())
226+
}
227+
208228
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
209229
// Taint flow from parameter to return value
210230
exists(FunctionInput modelIn, FunctionOutput modelOut |

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,17 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
264264
}
265265

266266
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
267-
iTo.(CopyInstruction).getSourceValue() = iFrom or
268-
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or
267+
iTo.(CopyInstruction).getSourceValue() = iFrom
268+
or
269+
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom
270+
or
269271
// Treat all conversions as flow, even conversions between different numeric types.
270-
iTo.(ConvertInstruction).getUnary() = iFrom or
271-
iTo.(InheritanceConversionInstruction).getUnary() = iFrom or
272+
iTo.(ConvertInstruction).getUnary() = iFrom
273+
or
274+
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom
275+
or
276+
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
277+
or
272278
// A chi instruction represents a point where a new value (the _partial_
273279
// operand) may overwrite an old value (the _total_ operand), but the alias
274280
// analysis couldn't determine that it surely will overwrite every bit of it or
@@ -278,10 +284,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
278284
// due to shortcomings of the alias analysis. We may get false flow in cases
279285
// where the data is indeed overwritten.
280286
//
281-
// Allowing flow through the partial operand would be more noisy, especially
282-
// for variables that have escaped: for soundness, the IR has to assume that
283-
// every write to an unknown address can affect every escaped variable, and
284-
// this assumption shows up as data flowing through partial chi operands.
287+
// Flow through the partial operand belongs in the taint-tracking libraries
288+
// for now.
285289
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
286290
}
287291

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,10 @@ class ConvertInstruction extends UnaryInstruction {
947947
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
948948
}
949949

950+
class CheckedConvertOrNullInstruction extends UnaryInstruction {
951+
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
952+
}
953+
950954
/**
951955
* Represents an instruction that converts between two addresses
952956
* related by inheritance.
@@ -987,7 +991,7 @@ class InheritanceConversionInstruction extends UnaryInstruction {
987991

988992
/**
989993
* Represents an instruction that converts from the address of a derived class
990-
* to the address of a direct non-virtual base class.
994+
* to the address of a base class.
991995
*/
992996
class ConvertToBaseInstruction extends InheritanceConversionInstruction {
993997
ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode }

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
8484
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
8585
)
8686
or
87+
// Conversion using dynamic_cast results in an unknown offset
88+
instr instanceof CheckedConvertOrNullInstruction and
89+
bitOffset = Ints::unknown()
90+
or
8791
// Converting to a derived class subtracts the offset of the base class.
8892
exists(ConvertToDerivedInstruction convert |
8993
convert = instr and

0 commit comments

Comments
 (0)