Skip to content

Commit 0443057

Browse files
authored
Merge branch 'main' into amammad-python-WebAppsConstatntSecretKeys
2 parents eb5529e + 66d13dc commit 0443057

File tree

111 files changed

+2790
-1291
lines changed

Some content is hidden

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

111 files changed

+2790
-1291
lines changed

cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ public void TestCppAutobuilderSuccess()
327327
{
328328
Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1;
329329
Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
330-
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
330+
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program^ Files^ ^(x86^)\Microsoft^ Visual^ Studio^ 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
331331
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
332332
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
333333
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0;

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,25 @@ private module Cached {
15201520
)
15211521
}
15221522

1523+
/**
1524+
* Holds if `operand.getDef() = instr`, but there exists a `StoreInstruction` that
1525+
* writes to an address that is equivalent to the value computed by `instr` in
1526+
* between `instr` and `operand`, and therefore there should not be flow from `*instr`
1527+
* to `*operand`.
1528+
*/
1529+
pragma[nomagic]
1530+
private predicate isStoredToBetween(Instruction instr, Operand operand) {
1531+
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand)) and
1532+
exists(StoreInstruction store, IRBlock block, int storeIndex, int instrIndex, int operandIndex |
1533+
store.getDestinationAddress() = instr and
1534+
block.getInstruction(storeIndex) = store and
1535+
block.getInstruction(instrIndex) = instr and
1536+
block.getInstruction(operandIndex) = operand.getUse() and
1537+
instrIndex < storeIndex and
1538+
storeIndex < operandIndex
1539+
)
1540+
}
1541+
15231542
private predicate indirectionInstructionFlow(
15241543
RawIndirectInstruction nodeFrom, IndirectOperand nodeTo
15251544
) {
@@ -1529,7 +1548,8 @@ private module Cached {
15291548
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand))
15301549
|
15311550
hasOperandAndIndex(nodeTo, operand, pragma[only_bind_into](indirectionIndex)) and
1532-
hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex))
1551+
hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex)) and
1552+
not isStoredToBetween(instr, operand)
15331553
)
15341554
}
15351555

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
66
private import DataFlowUtil
77
private import semmle.code.cpp.models.interfaces.PointerWrapper
88
private import DataFlowPrivate
9+
private import semmle.code.cpp.ir.ValueNumbering
910

1011
/**
1112
* Holds if `operand` is an operand that is not used by the dataflow library.
@@ -864,7 +865,7 @@ private module Cached {
864865
* to a specific address.
865866
*/
866867
private predicate isCertainAddress(Operand operand) {
867-
operand.getDef() instanceof VariableAddressInstruction
868+
valueNumberOfOperand(operand).getAnInstruction() instanceof VariableAddressInstruction
868869
or
869870
operand.getType() instanceof Cpp::ReferenceType
870871
}

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -574,16 +574,6 @@ module RangeStage<
574574
)
575575
}
576576

577-
/** Holds if `e >= 1` as determined by sign analysis. */
578-
private predicate strictlyPositiveIntegralExpr(SemExpr e) {
579-
semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType
580-
}
581-
582-
/** Holds if `e <= -1` as determined by sign analysis. */
583-
private predicate strictlyNegativeIntegralExpr(SemExpr e) {
584-
semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType
585-
}
586-
587577
/**
588578
* Holds if `e1 + delta` is a valid bound for `e2`.
589579
* - `upper = true` : `e2 <= e1 + delta`
@@ -597,27 +587,6 @@ module RangeStage<
597587
delta = D::fromInt(0) and
598588
(upper = true or upper = false)
599589
or
600-
exists(SemExpr x, SemSubExpr sub |
601-
e2 = sub and
602-
sub.getLeftOperand() = e1 and
603-
sub.getRightOperand() = x
604-
|
605-
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
606-
not x instanceof SemConstantIntegerExpr and
607-
if strictlyPositiveIntegralExpr(x)
608-
then upper = true and delta = D::fromInt(-1)
609-
else
610-
if semPositive(x)
611-
then upper = true and delta = D::fromInt(0)
612-
else
613-
if strictlyNegativeIntegralExpr(x)
614-
then upper = false and delta = D::fromInt(1)
615-
else
616-
if semNegative(x)
617-
then upper = false and delta = D::fromInt(0)
618-
else none()
619-
)
620-
or
621590
e2.(SemRemExpr).getRightOperand() = e1 and
622591
semPositive(e1) and
623592
delta = D::fromInt(-1) and
@@ -1137,6 +1106,23 @@ module RangeStage<
11371106
b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound
11381107
)
11391108
or
1109+
exists(D::Delta dLeft, D::Delta dRight, boolean fbeLeft, boolean fbeRight |
1110+
boundedSubOperandLeft(e, upper, b, dLeft, fbeLeft, origdelta, reason) and
1111+
boundedSubOperandRight(e, upper, dRight, fbeRight) and
1112+
// when `upper` is `true` we have:
1113+
// left <= b + dLeft
1114+
// right >= 0 + dRight
1115+
// left - right <= b + dLeft - (0 + dRight)
1116+
// = b + (dLeft - dRight)
1117+
// and when `upper` is `false` we have:
1118+
// left >= b + dLeft
1119+
// right <= 0 + dRight
1120+
// left - right >= b + dLeft - (0 + dRight)
1121+
// = b + (dLeft - dRight)
1122+
delta = D::fromFloat(D::toFloat(dLeft) - D::toFloat(dRight)) and
1123+
fromBackEdge = fbeLeft.booleanOr(fbeRight)
1124+
)
1125+
or
11401126
exists(
11411127
SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2,
11421128
D::Delta od1, D::Delta od2, SemReason r1, SemReason r2
@@ -1201,6 +1187,37 @@ module RangeStage<
12011187
)
12021188
}
12031189

1190+
/**
1191+
* Holds if `sub = left - right` and `left <= b + delta` if `upper` is `true`
1192+
* and `left >= b + delta` is `upper` is `false`.
1193+
*/
1194+
pragma[nomagic]
1195+
private predicate boundedSubOperandLeft(
1196+
SemSubExpr sub, boolean upper, SemBound b, D::Delta delta, boolean fromBackEdge,
1197+
D::Delta origdelta, SemReason reason
1198+
) {
1199+
// `semValueFlowStep` already handles the case where one of the operands is a constant.
1200+
not semValueFlowStep(sub, _, _) and
1201+
bounded(sub.getLeftOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
1202+
}
1203+
1204+
/**
1205+
* Holds if `sub = left - right` and `right <= 0 + delta` if `upper` is `false`
1206+
* and `right >= 0 + delta` is `upper` is `true`.
1207+
*
1208+
* Note that the boolean value of `upper` is flipped compared to many other predicates in
1209+
* this file. This ensures a clean join at the call-site.
1210+
*/
1211+
pragma[nomagic]
1212+
private predicate boundedSubOperandRight(
1213+
SemSubExpr sub, boolean upper, D::Delta delta, boolean fromBackEdge
1214+
) {
1215+
// `semValueFlowStep` already handles the case where one of the operands is a constant.
1216+
not semValueFlowStep(sub, _, _) and
1217+
bounded(sub.getRightOperand(), any(SemZeroBound zb), delta, upper.booleanNot(), fromBackEdge, _,
1218+
_)
1219+
}
1220+
12041221
pragma[nomagic]
12051222
private predicate boundedRemExpr(
12061223
SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta,

cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -96,57 +96,83 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
9696
* but because there's a strict comparison that compares `n` against the size of the allocation this
9797
* snippet is fine.
9898
*/
99-
module SizeBarrier {
99+
private module SizeBarrier {
100100
private module SizeBarrierConfig implements DataFlow::ConfigSig {
101101
predicate isSource(DataFlow::Node source) {
102102
// The sources is the same as in the sources for the second
103103
// projection in the `AllocToInvalidPointerConfig` module.
104104
hasSize(_, source, _)
105105
}
106106

107+
/**
108+
* Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`.
109+
*/
107110
additional predicate isSink(
108-
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, int k, boolean testIsTrue
111+
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
109112
) {
110-
// The sink is any "large" side of a relational comparison. i.e., the `right` expression
111-
// in a guard such as `left < right + k`.
112-
g.comparesLt(left.asOperand(), right.asOperand(), k, true, testIsTrue)
113+
// The sink is any "large" side of a relational comparison. i.e., the `large` expression
114+
// in a guard such as `small <= large + k`.
115+
g.comparesLt(small.asOperand(), large.asOperand(), k + 1, true, testIsTrue)
113116
}
114117

115118
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
116119
}
117120

118-
private import DataFlow::Global<SizeBarrierConfig>
121+
module SizeBarrierFlow = DataFlow::Global<SizeBarrierConfig>;
119122

120-
private int getAFlowStateForNode(DataFlow::Node node) {
123+
private int getASizeAddend(DataFlow::Node node) {
121124
exists(DataFlow::Node source |
122-
flow(source, node) and
125+
SizeBarrierFlow::flow(source, node) and
123126
hasSize(_, source, result)
124127
)
125128
}
126129

130+
/**
131+
* Holds if `small <= large + k` holds if `g` evaluates to `edge`.
132+
*/
127133
private predicate operandGuardChecks(
128-
IRGuardCondition g, Operand left, Operand right, int state, boolean edge
134+
IRGuardCondition g, Operand small, DataFlow::Node large, int k, boolean edge
129135
) {
130-
exists(DataFlow::Node nLeft, DataFlow::Node nRight, int k |
131-
nRight.asOperand() = right and
132-
nLeft.asOperand() = left and
133-
SizeBarrierConfig::isSink(nLeft, nRight, g, k, edge) and
134-
state = getAFlowStateForNode(nRight) and
135-
k <= state
136+
SizeBarrierFlow::flowTo(large) and
137+
SizeBarrierConfig::isSink(DataFlow::operandNode(small), large, g, k, edge)
138+
}
139+
140+
/**
141+
* Gets an instruction `instr` that is guarded by a check such as `instr <= small + delta` where
142+
* `small <= _ + k` and `small` is the "small side" of of a relational comparison that checks
143+
* whether `small <= size` where `size` is the size of an allocation.
144+
*/
145+
Instruction getABarrierInstruction0(int delta, int k) {
146+
exists(
147+
IRGuardCondition g, ValueNumber value, Operand small, boolean edge, DataFlow::Node large
148+
|
149+
// We know:
150+
// 1. result <= value + delta (by `bounded`)
151+
// 2. value <= large + k (by `operandGuardChecks`).
152+
// So:
153+
// result <= value + delta (by 1.)
154+
// <= large + k + delta (by 2.)
155+
small = value.getAUse() and
156+
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](small), large,
157+
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
158+
bounded(result, value.getAnInstruction(), delta) and
159+
g.controls(result.getBlock(), edge) and
160+
k < getASizeAddend(large)
136161
)
137162
}
138163

139164
/**
140165
* Gets an instruction that is guarded by a guard condition which ensures that
141166
* the value of the instruction is upper-bounded by size of some allocation.
142167
*/
168+
bindingset[state]
169+
pragma[inline_late]
143170
Instruction getABarrierInstruction(int state) {
144-
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
145-
use = value.getAUse() and
146-
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _,
147-
pragma[only_bind_into](state), pragma[only_bind_into](edge)) and
148-
result = value.getAnInstruction() and
149-
g.controls(result.getBlock(), edge)
171+
exists(int delta, int k |
172+
state > k + delta and
173+
// result <= "size of allocation" + delta + k
174+
// < "size of allocation" + state
175+
result = getABarrierInstruction0(delta, k)
150176
)
151177
}
152178

@@ -155,14 +181,16 @@ module SizeBarrier {
155181
* the value of the node is upper-bounded by size of some allocation.
156182
*/
157183
DataFlow::Node getABarrierNode(int state) {
158-
result.asOperand() = getABarrierInstruction(state).getAUse()
184+
exists(DataFlow::Node source, int delta, int k |
185+
SizeBarrierFlow::flow(source, result) and
186+
hasSize(_, source, state) and
187+
result.asInstruction() = SizeBarrier::getABarrierInstruction0(delta, k) and
188+
state > k + delta
189+
// so now we have:
190+
// result <= "size of allocation" + delta + k
191+
// < "size of allocation" + state
192+
)
159193
}
160-
161-
/**
162-
* Gets the block of a node that is guarded (see `getABarrierInstruction` or
163-
* `getABarrierNode` for the definition of what it means to be guarded).
164-
*/
165-
IRBlock getABarrierBlock(int state) { result.getAnInstruction() = getABarrierInstruction(state) }
166194
}
167195

168196
private module InterestingPointerAddInstruction {

0 commit comments

Comments
 (0)