Skip to content

Commit 6eac35c

Browse files
authored
Merge pull request github#3264 from Semmle/merge-rc/1.24
Merge rc/1.24 into master.
2 parents ae11e7b + 4e981d8 commit 6eac35c

File tree

36 files changed

+575
-156
lines changed

36 files changed

+575
-156
lines changed

cpp/ql/src/Options.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* By default they fall back to the reasonable defaults provided in
66
* `DefaultOptions.qll`, but by modifying this file, you can customize
7-
* the standard Semmle analyses to give better results for your project.
7+
* the standard analyses to give better results for your project.
88
*/
99

1010
import cpp

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ private predicate idOf(@compilation x, int y) = equivalenceRelation(id/2)(x, y)
2121
* Three things happen to each file during a compilation:
2222
*
2323
* 1. The file is compiled by a real compiler, such as gcc or VC.
24-
* 2. The file is parsed by Semmle's C++ front-end.
24+
* 2. The file is parsed by the CodeQL C++ front-end.
2525
* 3. The parsed representation is converted to database tables by
26-
* Semmle's extractor.
26+
* the CodeQL extractor.
2727
*
2828
* This class provides CPU and elapsed time information for steps 2 and 3,
2929
* but not for step 1.

cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* DEPRECATED: Recursion through `DataFlow::Configuration` is impossible in
3-
* Semmle Core 1.17 and above. There is no need for this module because it's
3+
* any supported tooling. There is no need for this module because it's
44
* impossible to accidentally depend on recursion through
55
* `DataFlow::Configuration` in current releases.
66
*

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,27 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
199199
// Flow through pointer dereference
200200
i2.(LoadInstruction).getSourceAddress() = i1
201201
or
202-
i2.(UnaryInstruction).getUnary() = i1
202+
// Flow through partial reads of arrays and unions
203+
i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 and
204+
not i1.isResultConflated() and
205+
(
206+
i1.getResultType() instanceof ArrayType or
207+
i1.getResultType() instanceof Union
208+
)
209+
or
210+
// Unary instructions tend to preserve enough information in practice that we
211+
// want taint to flow through.
212+
// The exception is `FieldAddressInstruction`. Together with the rule for
213+
// `LoadInstruction` above and for `ChiInstruction` below, flow through
214+
// `FieldAddressInstruction` could cause flow into one field to come out an
215+
// unrelated field. This would happen across function boundaries, where the IR
216+
// would not be able to match loads to stores.
217+
i2.(UnaryInstruction).getUnary() = i1 and
218+
(
219+
not i2 instanceof FieldAddressInstruction
220+
or
221+
i2.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
222+
)
203223
or
204224
// Flow out of definition-by-reference
205225
i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and
@@ -213,7 +233,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
213233
or
214234
t instanceof ArrayType
215235
or
216-
// Buffers or unknown size
236+
// Buffers of unknown size
217237
t instanceof UnknownType
218238
)
219239
or

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ private module VirtualDispatch {
7070
// Call return
7171
exists(DataFlowCall call, ReturnKind returnKind |
7272
other = getAnOutNode(call, returnKind) and
73-
src.(ReturnNode).getKind() = returnKind and
74-
call.getStaticCallTarget() = src.getEnclosingCallable()
73+
returnNodeWithKindAndEnclosingCallable(src, returnKind, call.getStaticCallTarget())
7574
) and
7675
allowFromArg = false
7776
or
@@ -125,6 +124,18 @@ private module VirtualDispatch {
125124
}
126125
}
127126

127+
/**
128+
* A ReturnNode with its ReturnKind and its enclosing callable.
129+
*
130+
* Used to fix a join ordering issue in flowsFrom.
131+
*/
132+
private predicate returnNodeWithKindAndEnclosingCallable(
133+
ReturnNode node, ReturnKind kind, DataFlowCallable callable
134+
) {
135+
node.getKind() = kind and
136+
node.getEnclosingCallable() = callable
137+
}
138+
128139
/** Call through a function pointer. */
129140
private class DataSensitiveExprCall extends DataSensitiveCall {
130141
DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) }

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

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,86 @@ class ArgumentNode extends InstructionNode {
2424
DataFlowCall getCall() { this.argumentOf(result, _) }
2525
}
2626

27-
private newtype TReturnKind = TNormalReturnKind()
27+
private newtype TReturnKind =
28+
TNormalReturnKind() or
29+
TIndirectReturnKind(ParameterIndex index)
2830

2931
/**
3032
* A return kind. A return kind describes how a value can be returned
3133
* from a callable. For C++, this is simply a function return.
3234
*/
3335
class ReturnKind extends TReturnKind {
3436
/** Gets a textual representation of this return kind. */
35-
string toString() { result = "return" }
37+
abstract string toString();
38+
}
39+
40+
private class NormalReturnKind extends ReturnKind, TNormalReturnKind {
41+
override string toString() { result = "return" }
42+
}
43+
44+
private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind {
45+
ParameterIndex index;
46+
47+
IndirectReturnKind() { this = TIndirectReturnKind(index) }
48+
49+
override string toString() { result = "outparam[" + index.toString() + "]" }
3650
}
3751

3852
/** A data flow node that occurs as the result of a `ReturnStmt`. */
3953
class ReturnNode extends InstructionNode {
40-
ReturnNode() { exists(ReturnValueInstruction ret | this.getInstruction() = ret.getReturnValue()) }
54+
Instruction primary;
55+
56+
ReturnNode() {
57+
exists(ReturnValueInstruction ret | instr = ret.getReturnValue() and primary = ret)
58+
or
59+
exists(ReturnIndirectionInstruction rii |
60+
instr = rii.getSideEffectOperand().getAnyDef() and primary = rii
61+
)
62+
}
4163

4264
/** Gets the kind of this returned value. */
43-
ReturnKind getKind() { result = TNormalReturnKind() }
65+
abstract ReturnKind getKind();
66+
}
67+
68+
class ReturnValueNode extends ReturnNode {
69+
override ReturnValueInstruction primary;
70+
71+
override ReturnKind getKind() { result = TNormalReturnKind() }
72+
}
73+
74+
class ReturnIndirectionNode extends ReturnNode {
75+
override ReturnIndirectionInstruction primary;
76+
77+
override ReturnKind getKind() { result = TIndirectReturnKind(primary.getParameter().getIndex()) }
4478
}
4579

4680
/** A data flow node that represents the output of a call. */
4781
class OutNode extends InstructionNode {
48-
override CallInstruction instr;
82+
OutNode() {
83+
instr instanceof CallInstruction or
84+
instr instanceof WriteSideEffectInstruction
85+
}
4986

5087
/** Gets the underlying call. */
51-
DataFlowCall getCall() { result = instr }
88+
abstract DataFlowCall getCall();
89+
90+
abstract ReturnKind getReturnKind();
91+
}
92+
93+
private class CallOutNode extends OutNode {
94+
override CallInstruction instr;
95+
96+
override DataFlowCall getCall() { result = instr }
97+
98+
override ReturnKind getReturnKind() { result instanceof NormalReturnKind }
99+
}
100+
101+
private class SideEffectOutNode extends OutNode {
102+
override WriteSideEffectInstruction instr;
103+
104+
override DataFlowCall getCall() { result = instr.getPrimaryInstruction() }
105+
106+
override ReturnKind getReturnKind() { result = TIndirectReturnKind(instr.getIndex()) }
52107
}
53108

54109
/**
@@ -57,7 +112,7 @@ class OutNode extends InstructionNode {
57112
*/
58113
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
59114
result.getCall() = call and
60-
kind = TNormalReturnKind()
115+
result.getReturnKind() = kind
61116
}
62117

63118
/**

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction {
525525
final Instruction getReturnValue() { result = getReturnValueOperand().getDef() }
526526
}
527527

528-
class ReturnIndirectionInstruction extends Instruction {
528+
class ReturnIndirectionInstruction extends VariableInstruction {
529529
ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection }
530530

531531
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
@@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction {
535535
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
536536

537537
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
538+
539+
/**
540+
* Gets the parameter for which this instruction reads the final pointed-to value within the
541+
* function.
542+
*/
543+
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
538544
}
539545

540546
class CopyInstruction extends Instruction {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction {
525525
final Instruction getReturnValue() { result = getReturnValueOperand().getDef() }
526526
}
527527

528-
class ReturnIndirectionInstruction extends Instruction {
528+
class ReturnIndirectionInstruction extends VariableInstruction {
529529
ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection }
530530

531531
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
@@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction {
535535
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
536536

537537
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
538+
539+
/**
540+
* Gets the parameter for which this instruction reads the final pointed-to value within the
541+
* function.
542+
*/
543+
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
538544
}
539545

540546
class CopyInstruction extends Instruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,4 +749,9 @@ class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect {
749749
operandTag = sideEffectOperand() and
750750
result = getUnknownType()
751751
}
752+
753+
final override IRVariable getInstructionVariable(InstructionTag tag) {
754+
tag = OnlyInstructionTag() and
755+
result = getIRUserVariable(getFunction(), param)
756+
}
752757
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction {
525525
final Instruction getReturnValue() { result = getReturnValueOperand().getDef() }
526526
}
527527

528-
class ReturnIndirectionInstruction extends Instruction {
528+
class ReturnIndirectionInstruction extends VariableInstruction {
529529
ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection }
530530

531531
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
@@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction {
535535
final AddressOperand getSourceAddressOperand() { result = getAnOperand() }
536536

537537
final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
538+
539+
/**
540+
* Gets the parameter for which this instruction reads the final pointed-to value within the
541+
* function.
542+
*/
543+
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
538544
}
539545

540546
class CopyInstruction extends Instruction {

0 commit comments

Comments
 (0)