Skip to content

Commit 05cad96

Browse files
author
Robert Marsh
authored
Merge pull request #1605 from geoffw0/bitwiseneg
CPP: Make BitwiseSignCheck.ql more accurate
2 parents fa43ae2 + 72d0178 commit 05cad96

File tree

4 files changed

+25
-6
lines changed

4 files changed

+25
-6
lines changed

change-notes/1.22/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
| Continue statement that does not continue (`cpp/continue-in-false-loop`) | Fewer false positive results | Analysis is now restricted to `do`-`while` loops. This query is now run and displayed by default on LGTM. |
1616
| Expression has no effect (`cpp/useless-expression`) | Fewer false positive results | Calls to functions with the `weak` attribute are no longer considered to be side effect free, because they could be overridden with a different implementation at link time. |
1717
| No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | False positives involving strings that are not null-terminated have been excluded. |
18+
| Sign check of bitwise operation (`cpp/bitwise-sign-check`) | Fewer false positive results and more true positive results | The query now understands the direction of each comparison, making it more accurate. |
1819
| Suspicious pointer scaling (`cpp/suspicious-pointer-scaling`) | Lower precision | The precision of this query has been reduced to "medium". This coding pattern is used intentionally and safely in a number of real-world projects. Results are no longer displayed on LGTM unless you choose to display them. |
1920
| Non-constant format string (`cpp/non-constant-format`) | Fewer false positive results | Rewritten using the taint-tracking library. |
2021
| Variable used in its own initializer (`cpp/use-in-own-initializer`) | Fewer false positive results | False positives for constant variables with the same name in different namespaces have been removed. |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
import cpp
1313

1414
from RelationalOperation e, BinaryBitwiseOperation lhs
15-
where lhs = e.getLeftOperand() and
15+
where lhs = e.getGreaterOperand() and
1616
lhs.getActualType().(IntegralType).isSigned() and
1717
forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and
18-
e.getRightOperand().getValue() = "0" and
18+
e.getLesserOperand().getValue() = "0" and
1919
not e.isAffectedByMacro()
2020
select e, "Potential unsafe sign check of a bitwise operation."
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
| bsc.cpp:2:10:2:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
22
| bsc.cpp:6:10:6:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
33
| bsc.cpp:10:10:10:33 | ... >= ... | Potential unsafe sign check of a bitwise operation. |
4+
| bsc.cpp:18:10:18:28 | ... > ... | Potential unsafe sign check of a bitwise operation. |
5+
| bsc.cpp:22:10:22:28 | ... < ... | Potential unsafe sign check of a bitwise operation. |
Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
bool is_bit_set_v1(int x, int bitnum) {
2-
return (x & (1 << bitnum)) > 0;
2+
return (x & (1 << bitnum)) > 0; // BAD
33
}
44

55
bool is_bit_set_v2(int x, int bitnum) {
6-
return ((1 << bitnum) & x) > 0;
6+
return ((1 << bitnum) & x) > 0; // BAD
77
}
88

99
bool plain_wrong(int x, int bitnum) {
10-
return (x & (1 << bitnum)) >= 0;
10+
return (x & (1 << bitnum)) >= 0; // ???
1111
}
1212

1313
bool is_bit24_set(int x) {
14-
return (x & (1 << 24)) > 0;
14+
return (x & (1 << 24)) > 0; // GOOD (result will always be positive)
15+
}
16+
17+
bool is_bit31_set_bad_v1(int x) {
18+
return (x & (1 << 31)) > 0; // BAD
19+
}
20+
21+
bool is_bit31_set_bad_v2(int x) {
22+
return 0 < (x & (1 << 31)); // BAD
23+
}
24+
25+
bool is_bit31_set_good(int x) {
26+
return (x & (1 << 31)) != 0; // GOOD (uses `!=`)
27+
}
28+
29+
bool deliberately_checking_sign(int x, int y) {
30+
return (x & y) < 0; // GOOD (use of `<` implies the sign check is intended)
1531
}

0 commit comments

Comments
 (0)