Skip to content

Commit 30ecb4b

Browse files
authored
Merge pull request github#14588 from aschackmull/shared/rangeanalysis
C++/Java: Share core range analysis
2 parents 867a390 + 6882504 commit 30ecb4b

File tree

22 files changed

+980
-1106
lines changed

22 files changed

+980
-1106
lines changed

cpp/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ library: true
77
upgrades: upgrades
88
dependencies:
99
codeql/dataflow: ${workspace}
10+
codeql/rangeanalysis: ${workspace}
1011
codeql/ssa: ${workspace}
1112
codeql/tutorial: ${workspace}
1213
codeql/util: ${workspace}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ class SemLocation instanceof Location {
88
*/
99
string toString() { result = super.toString() }
1010

11+
/** Gets the 1-based line number (inclusive) where this location starts. */
12+
int getStartLine() { result = super.getStartLine() }
13+
14+
/** Gets the 1-based column number (inclusive) where this location starts. */
15+
int getStartColumn() { result = super.getStartColumn() }
16+
17+
/** Gets the 1-based line number (inclusive) where this location ends. */
18+
int getEndLine() { result = super.getEndLine() }
19+
20+
/** Gets the 1-based column number (inclusive) where this location ends. */
21+
int getEndColumn() { result = super.getEndColumn() }
22+
1123
/**
1224
* Holds if this element is at the specified location.
1325
* The location spans column `startcolumn` of line `startline` to

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
private import RangeAnalysisStage
21
private import RangeAnalysisImpl
2+
private import codeql.rangeanalysis.RangeAnalysis
3+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExpr
4+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticType
35

46
module FloatDelta implements DeltaSig {
57
class Delta = float;
@@ -20,7 +22,7 @@ module FloatDelta implements DeltaSig {
2022
Delta fromFloat(float f) { result = f }
2123
}
2224

23-
module FloatOverflow implements OverflowSig<FloatDelta> {
25+
module FloatOverflow implements OverflowSig<Sem, FloatDelta> {
2426
predicate semExprDoesNotOverflow(boolean positively, SemExpr expr) {
2527
exists(float lb, float ub, float delta |
2628
typeBounds(expr.getSemType(), lb, ub) and

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

Lines changed: 0 additions & 29 deletions
This file was deleted.

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212

1313
private import ModulusAnalysisSpecific::Private
1414
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
15+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation
1516
private import ConstantAnalysis
1617
private import RangeUtils
17-
private import RangeAnalysisStage
18+
private import codeql.rangeanalysis.RangeAnalysis
19+
private import RangeAnalysisImpl
1820

19-
module ModulusAnalysis<DeltaSig D, BoundSig<D> Bounds, UtilSig<D> U> {
21+
module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig<Sem, D> U> {
2022
pragma[nomagic]
2123
private predicate valueFlowStepSsaEqFlowCond(
2224
SemSsaReadPosition pos, SemSsaVariable v, SemExpr e, int delta

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
*/
44

55
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
6-
private import RangeAnalysisStage
76
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
7+
private import RangeAnalysisImpl
8+
private import codeql.rangeanalysis.RangeAnalysis
89

9-
module CppLangImplConstant implements LangSig<FloatDelta> {
10+
module CppLangImplConstant implements LangSig<Sem, FloatDelta> {
1011
/**
1112
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
1213
*

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

Lines changed: 123 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,104 @@
1-
private import RangeAnalysisStage
21
private import RangeAnalysisConstantSpecific
32
private import RangeAnalysisRelativeSpecific
43
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
54
private import RangeUtils
5+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExpr
6+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticCFG
7+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticGuard
68
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound as SemanticBound
79
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation
810
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticSSA
11+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticType as SemanticType
12+
private import SemanticType
13+
private import codeql.rangeanalysis.RangeAnalysis
14+
private import ConstantAnalysis as ConstantAnalysis
915

10-
module ConstantBounds implements BoundSig<FloatDelta> {
16+
module Sem implements Semantic {
17+
class Expr = SemExpr;
18+
19+
class ConstantIntegerExpr = ConstantAnalysis::SemConstantIntegerExpr;
20+
21+
class BinaryExpr = SemBinaryExpr;
22+
23+
class AddExpr = SemAddExpr;
24+
25+
class SubExpr = SemSubExpr;
26+
27+
class MulExpr = SemMulExpr;
28+
29+
class DivExpr = SemDivExpr;
30+
31+
class RemExpr = SemRemExpr;
32+
33+
class BitAndExpr = SemBitAndExpr;
34+
35+
class BitOrExpr = SemBitOrExpr;
36+
37+
class ShiftLeftExpr = SemShiftLeftExpr;
38+
39+
class ShiftRightExpr = SemShiftRightExpr;
40+
41+
class ShiftRightUnsignedExpr = SemShiftRightUnsignedExpr;
42+
43+
class RelationalExpr = SemRelationalExpr;
44+
45+
class UnaryExpr = SemUnaryExpr;
46+
47+
class ConvertExpr = SemConvertExpr;
48+
49+
class BoxExpr = SemBoxExpr;
50+
51+
class UnboxExpr = SemUnboxExpr;
52+
53+
class NegateExpr = SemNegateExpr;
54+
55+
class AddOneExpr = SemAddOneExpr;
56+
57+
class SubOneExpr = SemSubOneExpr;
58+
59+
class ConditionalExpr = SemConditionalExpr;
60+
61+
class BasicBlock = SemBasicBlock;
62+
63+
class Guard = SemGuard;
64+
65+
predicate implies_v2 = semImplies_v2/4;
66+
67+
predicate guardDirectlyControlsSsaRead = semGuardDirectlyControlsSsaRead/3;
68+
69+
class Type = SemType;
70+
71+
class IntegerType = SemIntegerType;
72+
73+
class FloatingPointType = SemFloatingPointType;
74+
75+
class AddressType = SemAddressType;
76+
77+
class SsaVariable = SemSsaVariable;
78+
79+
class SsaPhiNode = SemSsaPhiNode;
80+
81+
class SsaExplicitUpdate = SemSsaExplicitUpdate;
82+
83+
class SsaReadPosition = SemSsaReadPosition;
84+
85+
class SsaReadPositionPhiInputEdge = SemSsaReadPositionPhiInputEdge;
86+
87+
class SsaReadPositionBlock = SemSsaReadPositionBlock;
88+
89+
predicate backEdge = semBackEdge/3;
90+
91+
predicate conversionCannotOverflow(Type fromType, Type toType) {
92+
SemanticType::conversionCannotOverflow(fromType, toType)
93+
}
94+
}
95+
96+
module SignAnalysis implements SignAnalysisSig<Sem> {
97+
private import SignAnalysisCommon as SA
98+
import SA::SignAnalysis<FloatDelta, Util>
99+
}
100+
101+
module ConstantBounds implements BoundSig<SemLocation, Sem, FloatDelta> {
11102
class SemBound instanceof SemanticBound::SemBound {
12103
SemBound() {
13104
this instanceof SemanticBound::SemZeroBound
@@ -29,7 +120,7 @@ module ConstantBounds implements BoundSig<FloatDelta> {
29120
}
30121
}
31122

32-
module RelativeBounds implements BoundSig<FloatDelta> {
123+
module RelativeBounds implements BoundSig<SemLocation, Sem, FloatDelta> {
33124
class SemBound instanceof SemanticBound::SemBound {
34125
SemBound() { not this instanceof SemanticBound::SemZeroBound }
35126

@@ -47,13 +138,38 @@ module RelativeBounds implements BoundSig<FloatDelta> {
47138
}
48139
}
49140

141+
module AllBounds implements BoundSig<SemLocation, Sem, FloatDelta> {
142+
class SemBound instanceof SemanticBound::SemBound {
143+
string toString() { result = super.toString() }
144+
145+
SemLocation getLocation() { result = super.getLocation() }
146+
147+
SemExpr getExpr(float delta) { result = super.getExpr(delta) }
148+
}
149+
150+
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
151+
152+
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
153+
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
154+
}
155+
}
156+
157+
private module ModulusAnalysisInstantiated implements ModulusAnalysisSig<Sem> {
158+
class ModBound = AllBounds::SemBound;
159+
160+
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.ModulusAnalysis as MA
161+
import MA::ModulusAnalysis<FloatDelta, AllBounds, Util>
162+
}
163+
164+
module Util = RangeUtil<FloatDelta, CppLangImplConstant>;
165+
50166
module ConstantStage =
51-
RangeStage<FloatDelta, ConstantBounds, FloatOverflow, CppLangImplConstant,
52-
RangeUtil<FloatDelta, CppLangImplConstant>>;
167+
RangeStage<SemLocation, Sem, FloatDelta, ConstantBounds, FloatOverflow, CppLangImplConstant,
168+
SignAnalysis, ModulusAnalysisInstantiated, Util>;
53169

54170
module RelativeStage =
55-
RangeStage<FloatDelta, RelativeBounds, FloatOverflow, CppLangImplRelative,
56-
RangeUtil<FloatDelta, CppLangImplRelative>>;
171+
RangeStage<SemLocation, Sem, FloatDelta, RelativeBounds, FloatOverflow, CppLangImplRelative,
172+
SignAnalysis, ModulusAnalysisInstantiated, Util>;
57173

58174
private newtype TSemReason =
59175
TSemNoReason() or

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
*/
44

55
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
6-
private import RangeAnalysisStage
76
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
8-
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.IntDelta
97
private import RangeAnalysisImpl
108
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
9+
private import codeql.rangeanalysis.RangeAnalysis
1110

12-
module CppLangImplRelative implements LangSig<FloatDelta> {
11+
module CppLangImplRelative implements LangSig<Sem, FloatDelta> {
1312
/**
1413
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
1514
*

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

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
66
private import RangeAnalysisRelativeSpecific
7-
private import RangeAnalysisStage as Range
7+
private import codeql.rangeanalysis.RangeAnalysis
8+
private import RangeAnalysisImpl
89
private import ConstantAnalysis
910

10-
module RangeUtil<Range::DeltaSig D, Range::LangSig<D> Lang> implements Range::UtilSig<D> {
11+
module RangeUtil<DeltaSig D, LangSig<Sem, D> Lang> implements UtilSig<Sem, D> {
1112
/**
1213
* Gets an expression that equals `v - d`.
1314
*/
@@ -138,27 +139,33 @@ module RangeUtil<Range::DeltaSig D, Range::LangSig<D> Lang> implements Range::Ut
138139
or
139140
not exists(Lang::getAlternateTypeForSsaVariable(var)) and result = var.getType()
140141
}
141-
}
142142

143-
/**
144-
* Holds if `rix` is the number of input edges to `phi`.
145-
*/
146-
predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
147-
rix = max(int r | rankedPhiInput(phi, _, _, r))
143+
import Ranking
148144
}
149145

150-
/**
151-
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
152-
* in an arbitrary 1-based numbering of the input edges to `phi`.
153-
*/
154-
predicate rankedPhiInput(
155-
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
156-
) {
157-
edge.phiInput(phi, inp) and
158-
edge =
159-
rank[r](SemSsaReadPositionPhiInputEdge e |
160-
e.phiInput(phi, _)
161-
|
162-
e order by e.getOrigBlock().getUniqueId()
163-
)
146+
import Ranking
147+
148+
module Ranking {
149+
/**
150+
* Holds if `rix` is the number of input edges to `phi`.
151+
*/
152+
predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
153+
rix = max(int r | rankedPhiInput(phi, _, _, r))
154+
}
155+
156+
/**
157+
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
158+
* in an arbitrary 1-based numbering of the input edges to `phi`.
159+
*/
160+
predicate rankedPhiInput(
161+
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
162+
) {
163+
edge.phiInput(phi, inp) and
164+
edge =
165+
rank[r](SemSsaReadPositionPhiInputEdge e |
166+
e.phiInput(phi, _)
167+
|
168+
e order by e.getOrigBlock().getUniqueId()
169+
)
170+
}
164171
}

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
* three-valued domain `{negative, zero, positive}`.
77
*/
88

9-
private import RangeAnalysisStage
9+
private import codeql.rangeanalysis.RangeAnalysis
10+
private import RangeAnalysisImpl
1011
private import SignAnalysisSpecific as Specific
1112
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
1213
private import ConstantAnalysis
1314
private import RangeUtils
1415
private import Sign
1516

16-
module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
17+
module SignAnalysis<DeltaSig D, UtilSig<Sem, D> Utils> {
1718
/**
1819
* An SSA definition for which the analysis can compute the sign.
1920
*
@@ -507,4 +508,16 @@ module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
507508
not semExprSign(e) = TPos() and
508509
not semExprSign(e) = TZero()
509510
}
511+
512+
/**
513+
* Holds if `e` may have positive values. This does not rule out the
514+
* possibility for negative values.
515+
*/
516+
predicate semMayBePositive(SemExpr e) { semExprSign(e) = TPos() }
517+
518+
/**
519+
* Holds if `e` may have negative values. This does not rule out the
520+
* possibility for positive values.
521+
*/
522+
predicate semMayBeNegative(SemExpr e) { semExprSign(e) = TNeg() }
510523
}

0 commit comments

Comments
 (0)