Skip to content

Commit 885df87

Browse files
authored
Merge pull request #1165 from dave-bartolomeo/dave/CompareFP
C++: Fix FP in PointlessComparison due to preprocessor
2 parents fa26087 + 127b759 commit 885df87

File tree

4 files changed

+85
-50
lines changed

4 files changed

+85
-50
lines changed

cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* readability
1313
*/
1414
import cpp
15+
private import semmle.code.cpp.commons.Exclusions
1516
private import semmle.code.cpp.rangeanalysis.PointlessComparison
1617
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
1718
import UnsignedGEZero
@@ -31,6 +32,7 @@ from
3132
where
3233
not cmp.isInMacroExpansion() and
3334
not cmp.isFromTemplateInstantiation(_) and
35+
not functionContainsDisabledCode(cmp.getEnclosingFunction()) and
3436
reachablePointlessComparison(cmp, left, right, value, ss) and
3537

3638
// a comparison between an enum and zero is always valid because whether

cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* external/cwe/cwe-561
1212
*/
1313
import cpp
14+
private import semmle.code.cpp.commons.Exclusions
1415

1516
class PureExprInVoidContext extends ExprInVoidContext {
1617
PureExprInVoidContext() { this.isPure() }
@@ -23,71 +24,29 @@ predicate accessInInitOfForStmt(Expr e) {
2324
s.getExpr() = e)
2425
}
2526

26-
/**
27-
* Holds if the preprocessor branch `pbd` is on line `pbdStartLine` in file `file`.
28-
*/
29-
predicate pbdLocation(PreprocessorBranchDirective pbd, string file, int pbdStartLine) {
30-
pbd.getLocation().hasLocationInfo(file, pbdStartLine, _, _, _)
31-
}
32-
33-
/**
34-
* Holds if the body of the function `f` is on lines `fBlockStartLine` to `fBlockEndLine` in file `file`.
35-
*/
36-
predicate functionLocation(Function f, string file, int fBlockStartLine, int fBlockEndLine) {
37-
f.getBlock().getLocation().hasLocationInfo(file, fBlockStartLine, _, fBlockEndLine, _)
38-
}
3927
/**
4028
* Holds if the function `f`, or a function called by it, contains
4129
* code excluded by the preprocessor.
4230
*/
43-
predicate containsDisabledCode(Function f) {
44-
// `f` contains a preprocessor branch that was not taken
45-
exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, int fBlockEndLine |
46-
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
47-
pbdLocation(pbd, file, pbdStartLine) and
48-
pbdStartLine <= fBlockEndLine and
49-
pbdStartLine >= fBlockStartLine and
50-
(
51-
pbd.(PreprocessorBranch).wasNotTaken() or
52-
53-
// an else either was not taken, or it's corresponding branch
54-
// was not taken.
55-
pbd instanceof PreprocessorElse
56-
)
57-
) or
58-
31+
predicate functionContainsDisabledCodeRecursive(Function f) {
32+
functionContainsDisabledCode(f) or
5933
// recurse into function calls
6034
exists(FunctionCall fc |
6135
fc.getEnclosingFunction() = f and
62-
containsDisabledCode(fc.getTarget())
36+
functionContainsDisabledCodeRecursive(fc.getTarget())
6337
)
6438
}
6539

66-
6740
/**
6841
* Holds if the function `f`, or a function called by it, is inside a
6942
* preprocessor branch that may have code in another arm
7043
*/
71-
predicate definedInIfDef(Function f) {
72-
exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int pbdEndLine, int fBlockStartLine, int fBlockEndLine |
73-
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
74-
pbdLocation(pbd, file, pbdStartLine) and
75-
pbdLocation(pbd.getNext(), file, pbdEndLine) and
76-
pbdStartLine <= fBlockStartLine and
77-
pbdEndLine >= fBlockEndLine and
78-
// pbd is a preprocessor branch where multiple branches exist
79-
(
80-
pbd.getNext() instanceof PreprocessorElse or
81-
pbd instanceof PreprocessorElse or
82-
pbd.getNext() instanceof PreprocessorElif or
83-
pbd instanceof PreprocessorElif
84-
)
85-
) or
86-
44+
predicate functionDefinedInIfDefRecursive(Function f) {
45+
functionDefinedInIfDef(f) or
8746
// recurse into function calls
8847
exists(FunctionCall fc |
8948
fc.getEnclosingFunction() = f and
90-
definedInIfDef(fc.getTarget())
49+
functionDefinedInIfDefRecursive(fc.getTarget())
9150
)
9251
}
9352

@@ -121,8 +80,8 @@ where // EQExprs are covered by CompareWhereAssignMeant.ql
12180
not parent instanceof PureExprInVoidContext and
12281
not peivc.getEnclosingFunction().isCompilerGenerated() and
12382
not peivc.getType() instanceof UnknownType and
124-
not containsDisabledCode(peivc.(FunctionCall).getTarget()) and
125-
not definedInIfDef(peivc.(FunctionCall).getTarget()) and
83+
not functionContainsDisabledCodeRecursive(peivc.(FunctionCall).getTarget()) and
84+
not functionDefinedInIfDefRecursive(peivc.(FunctionCall).getTarget()) and
12685
if peivc instanceof FunctionCall then
12786
exists(Function target |
12887
target = peivc.(FunctionCall).getTarget() and
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Common predicates used to exclude results from a query based on heuristics.
3+
*/
4+
5+
import cpp
6+
7+
/**
8+
* Holds if the preprocessor branch `pbd` is on line `pbdStartLine` in file `file`.
9+
*/
10+
private predicate pbdLocation(PreprocessorBranchDirective pbd, string file, int pbdStartLine) {
11+
pbd.getLocation().hasLocationInfo(file, pbdStartLine, _, _, _)
12+
}
13+
14+
/**
15+
* Holds if the body of the function `f` is on lines `fBlockStartLine` to `fBlockEndLine` in file `file`.
16+
*/
17+
private predicate functionLocation(Function f, string file, int fBlockStartLine, int fBlockEndLine) {
18+
f.getBlock().getLocation().hasLocationInfo(file, fBlockStartLine, _, fBlockEndLine, _)
19+
}
20+
21+
/**
22+
* Holds if the function `f` is inside a preprocessor branch that may have code in another arm.
23+
*/
24+
predicate functionDefinedInIfDef(Function f) {
25+
exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int pbdEndLine, int fBlockStartLine,
26+
int fBlockEndLine |
27+
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
28+
pbdLocation(pbd, file, pbdStartLine) and
29+
pbdLocation(pbd.getNext(), file, pbdEndLine) and
30+
pbdStartLine <= fBlockStartLine and
31+
pbdEndLine >= fBlockEndLine and
32+
// pbd is a preprocessor branch where multiple branches exist
33+
(
34+
pbd.getNext() instanceof PreprocessorElse or
35+
pbd instanceof PreprocessorElse or
36+
pbd.getNext() instanceof PreprocessorElif or
37+
pbd instanceof PreprocessorElif
38+
)
39+
)
40+
}
41+
42+
/**
43+
* Holds if the function `f` contains code excluded by the preprocessor.
44+
*/
45+
predicate functionContainsDisabledCode(Function f) {
46+
// `f` contains a preprocessor branch that was not taken
47+
exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, int fBlockEndLine |
48+
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
49+
pbdLocation(pbd, file, pbdStartLine) and
50+
pbdStartLine <= fBlockEndLine and
51+
pbdStartLine >= fBlockStartLine and
52+
(
53+
pbd.(PreprocessorBranch).wasNotTaken() or
54+
55+
// an else either was not taken, or it's corresponding branch
56+
// was not taken.
57+
pbd instanceof PreprocessorElse
58+
)
59+
)
60+
}

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/RegressionTests.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,17 @@ int regression_test_01(unsigned long bb) {
6666
return 1;
6767
}
6868
}
69+
70+
int containsIfDef(int x) {
71+
int result = 0;
72+
if (x > 0) {
73+
result = 1;
74+
}
75+
#if _CONDITION
76+
if (x < 0) {
77+
result = -1;
78+
}
79+
#endif
80+
81+
return result >= 0;
82+
}

0 commit comments

Comments
 (0)