Merge pull request #20218 from MathiasVP/fix-guard-conditions-for-likely

C++: Improvements to `IRGuard`s
This commit is contained in:
Jeroen Ketema
2025-08-14 10:24:48 +02:00
committed by GitHub
15 changed files with 2721 additions and 1962 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The guards libraries (`semmle.code.cpp.controlflow.Guards` and `semmle.code.cpp.controlflow.IRGuards`) have been improved to recognize more guards.

View File

@@ -936,6 +936,77 @@ private module Cached {
ValueNumber getUnary() { result.getAnInstruction() = instr.getUnary() }
}
signature predicate sinkSig(Instruction instr);
private module BooleanInstruction<sinkSig/1 isSink> {
/**
* Holds if `i1` flows to `i2` in a single step and `i2` is not an
* instruction that produces a value of Boolean type.
*/
private predicate stepToNonBoolean(Instruction i1, Instruction i2) {
not i2.getResultIRType() instanceof IRBooleanType and
(
i2.(CopyInstruction).getSourceValue() = i1
or
i2.(ConvertInstruction).getUnary() = i1
or
i2.(BuiltinExpectCallInstruction).getArgument(0) = i1
)
}
private predicate rev(Instruction instr) {
isSink(instr)
or
exists(Instruction instr1 |
rev(instr1) and
stepToNonBoolean(instr, instr1)
)
}
private predicate hasBooleanType(Instruction instr) {
instr.getResultIRType() instanceof IRBooleanType
}
private predicate fwd(Instruction instr) {
rev(instr) and
(
hasBooleanType(instr)
or
exists(Instruction instr0 |
fwd(instr0) and
stepToNonBoolean(instr0, instr)
)
)
}
private predicate prunedStep(Instruction i1, Instruction i2) {
fwd(i1) and
fwd(i2) and
stepToNonBoolean(i1, i2)
}
private predicate stepsPlus(Instruction i1, Instruction i2) =
doublyBoundedFastTC(prunedStep/2, hasBooleanType/1, isSink/1)(i1, i2)
/**
* Gets the Boolean-typed instruction that defines `instr` before any
* integer conversions are applied, if any.
*/
Instruction get(Instruction instr) {
isSink(instr) and
(
result = instr
or
stepsPlus(result, instr)
) and
hasBooleanType(result)
}
}
private predicate isUnaryComparesEqLeft(Instruction instr) {
unary_compares_eq(_, instr.getAUse(), 0, _, _)
}
/**
* Holds if `left == right + k` is `areEqual` given that test is `testIsTrue`.
*
@@ -966,14 +1037,19 @@ private module Cached {
)
or
compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), left, right, k, areEqual, value)
}
private predicate isConvertedBool(Instruction instr) {
instr.getResultIRType() instanceof IRBooleanType
or
isConvertedBool(instr.(ConvertInstruction).getUnary())
or
isConvertedBool(instr.(BuiltinExpectCallInstruction).getCondition())
exists(Operand l, BooleanValue bv |
// 1. test = value -> int(l) = 0 is !bv
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
// 2. l = bv -> left + right is areEqual
compares_eq(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())), left,
right, k, areEqual, bv)
// We want this to hold:
// `test = value -> left + right is areEqual`
// Applying 2 we need to show:
// `test = value -> l = bv`
// And `l = bv` holds by `int(l) = 0 is !bv`
)
}
/**
@@ -1006,19 +1082,11 @@ private module Cached {
k = k1 + k2
)
or
exists(CompareValueNumber cmp, Operand left, Operand right, AbstractValue v |
test = cmp and
pragma[only_bind_into](cmp)
.hasOperands(pragma[only_bind_into](left), pragma[only_bind_into](right)) and
isConvertedBool(left.getDef()) and
int_value(right.getDef()) = 0 and
unary_compares_eq(valueNumberOfOperand(left), op, k, areEqual, v)
|
cmp instanceof CompareNEValueNumber and
v = value
or
cmp instanceof CompareEQValueNumber and
v.getDualValue() = value
// See argument for why this is correct in compares_eq
exists(Operand l, BooleanValue bv |
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
unary_compares_eq(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())),
op, k, areEqual, bv)
)
or
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual, value)
@@ -1116,70 +1184,26 @@ private module Cached {
)
}
private predicate isBuiltInExpectArg(Instruction instr) {
instr = any(BuiltinExpectCallInstruction buildinExpect).getArgument(0)
}
/** A call to the builtin operation `__builtin_expect`. */
private class BuiltinExpectCallInstruction extends CallInstruction {
BuiltinExpectCallInstruction() { this.getStaticCallTarget().hasName("__builtin_expect") }
/** Gets the condition of this call. */
Instruction getCondition() { result = this.getConditionOperand().getDef() }
Operand getConditionOperand() {
// The first parameter of `__builtin_expect` has type `long`. So we skip
// the conversion when inferring guards.
result = this.getArgument(0).(ConvertInstruction).getUnaryOperand()
Instruction getCondition() {
result = BooleanInstruction<isBuiltInExpectArg/1>::get(this.getArgument(0))
}
}
/**
* Holds if `left == right + k` is `areEqual` if `cmp` evaluates to `value`,
* and `cmp` is an instruction that compares the value of
* `__builtin_expect(left == right + k, _)` to `0`.
*/
private predicate builtin_expect_eq(
CompareValueNumber cmp, Operand left, Operand right, int k, boolean areEqual,
AbstractValue value
) {
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
int_value(const) = 0 and
cmp.hasOperands(call.getAUse(), const.getAUse()) and
compares_eq(call.getCondition(), left, right, k, areEqual, innerValue)
|
cmp instanceof CompareNEValueNumber and
value = innerValue
or
cmp instanceof CompareEQValueNumber and
value.getDualValue() = innerValue
)
}
private predicate complex_eq(
ValueNumber cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
sub_eq(cmp, left, right, k, areEqual, value)
or
add_eq(cmp, left, right, k, areEqual, value)
or
builtin_expect_eq(cmp, left, right, k, areEqual, value)
}
/**
* Holds if `op == k` is `areEqual` if `cmp` evaluates to `value`, and `cmp` is
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
*/
private predicate unary_builtin_expect_eq(
CompareValueNumber cmp, Operand op, int k, boolean areEqual, AbstractValue value
) {
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
int_value(const) = 0 and
cmp.hasOperands(call.getAUse(), const.getAUse()) and
unary_compares_eq(call.getCondition(), op, k, areEqual, innerValue)
|
cmp instanceof CompareNEValueNumber and
value = innerValue
or
cmp instanceof CompareEQValueNumber and
value.getDualValue() = innerValue
)
}
private predicate unary_complex_eq(
@@ -1188,8 +1212,6 @@ private module Cached {
unary_sub_eq(test, op, k, areEqual, value)
or
unary_add_eq(test, op, k, areEqual, value)
or
unary_builtin_expect_eq(test, op, k, areEqual, value)
}
/*
@@ -1215,6 +1237,15 @@ private module Cached {
exists(AbstractValue dual | value = dual.getDualValue() |
compares_lt(test.(LogicalNotValueNumber).getUnary(), left, right, k, isLt, dual)
)
or
compares_lt(test.(BuiltinExpectCallValueNumber).getCondition(), left, right, k, isLt, value)
or
// See argument for why this is correct in compares_eq
exists(Operand l, BooleanValue bv |
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
compares_lt(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())), left,
right, k, isLt, bv)
)
}
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
@@ -1234,6 +1265,15 @@ private module Cached {
int_value(const) = k1 and
k = k1 + k2
)
or
compares_lt(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, isLt, value)
or
// See argument for why this is correct in compares_eq
exists(Operand l, BooleanValue bv |
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
compares_lt(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())), op, k,
isLt, bv)
)
}
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */

View File

@@ -44,6 +44,8 @@
| test.c:198:8:198:8 | b |
| test.c:206:7:206:8 | ! ... |
| test.c:206:8:206:8 | c |
| test.c:215:6:215:18 | call to __builtin_expect |
| test.c:219:9:219:22 | call to __builtin_expect |
| test.cpp:18:8:18:10 | call to get |
| test.cpp:31:7:31:13 | ... == ... |
| test.cpp:42:13:42:20 | call to getABool |
@@ -92,3 +94,15 @@
| test.cpp:241:9:241:43 | ... && ... |
| test.cpp:241:22:241:30 | ... == ... |
| test.cpp:241:35:241:43 | ... == ... |
| test.cpp:247:6:247:18 | ... == ... |
| test.cpp:253:6:253:18 | ... != ... |
| test.cpp:260:6:260:18 | ... == ... |
| test.cpp:266:6:266:18 | ... != ... |
| test.cpp:273:6:273:17 | ... == ... |
| test.cpp:279:6:279:17 | ... != ... |
| test.cpp:287:6:287:19 | ... == ... |
| test.cpp:293:6:293:19 | ... != ... |
| test.cpp:300:6:300:19 | ... == ... |
| test.cpp:306:6:306:19 | ... != ... |
| test.cpp:312:6:312:18 | ... == ... |
| test.cpp:318:6:318:18 | ... != ... |

View File

@@ -38,4 +38,4 @@ where
|
msg = left + op + k + " when " + guard + " is " + value
)
select guard.getLocation().getStartLine(), msg
select guard, msg

View File

@@ -1,165 +1,196 @@
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
| test.c:17:8:17:12 | ... < ... | true | 17 | 17 |
| test.c:17:8:17:12 | ... < ... | true | 18 | 18 |
| test.c:17:8:17:21 | ... && ... | true | 18 | 18 |
| test.c:17:17:17:21 | ... > ... | true | 18 | 18 |
| test.c:26:11:26:15 | ... > ... | false | 2 | 2 |
| test.c:26:11:26:15 | ... > ... | false | 31 | 34 |
| test.c:26:11:26:15 | ... > ... | false | 34 | 34 |
| test.c:26:11:26:15 | ... > ... | false | 39 | 42 |
| test.c:26:11:26:15 | ... > ... | false | 42 | 42 |
| test.c:26:11:26:15 | ... > ... | false | 42 | 44 |
| test.c:26:11:26:15 | ... > ... | false | 45 | 45 |
| test.c:26:11:26:15 | ... > ... | false | 45 | 47 |
| test.c:26:11:26:15 | ... > ... | false | 51 | 53 |
| test.c:26:11:26:15 | ... > ... | false | 56 | 58 |
| test.c:26:11:26:15 | ... > ... | false | 58 | 58 |
| test.c:26:11:26:15 | ... > ... | false | 58 | 66 |
| test.c:26:11:26:15 | ... > ... | false | 62 | 62 |
| test.c:26:11:26:15 | ... > ... | true | 26 | 28 |
| test.c:34:16:34:21 | ... < ... | false | 2 | 2 |
| test.c:34:16:34:21 | ... < ... | false | 39 | 42 |
| test.c:34:16:34:21 | ... < ... | false | 42 | 42 |
| test.c:34:16:34:21 | ... < ... | false | 42 | 44 |
| test.c:34:16:34:21 | ... < ... | false | 45 | 45 |
| test.c:34:16:34:21 | ... < ... | false | 45 | 47 |
| test.c:34:16:34:21 | ... < ... | false | 51 | 53 |
| test.c:34:16:34:21 | ... < ... | false | 56 | 58 |
| test.c:34:16:34:21 | ... < ... | false | 58 | 58 |
| test.c:34:16:34:21 | ... < ... | false | 58 | 66 |
| test.c:34:16:34:21 | ... < ... | false | 62 | 62 |
| test.c:34:16:34:21 | ... < ... | true | 34 | 34 |
| test.c:42:16:42:21 | ... < ... | true | 42 | 42 |
| test.c:42:16:42:21 | ... < ... | true | 42 | 44 |
| test.c:42:16:42:21 | ... < ... | true | 45 | 45 |
| test.c:42:16:42:21 | ... < ... | true | 45 | 47 |
| test.c:42:16:42:21 | ... < ... | true | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | false | 42 | 42 |
| test.c:44:12:44:16 | ... > ... | false | 51 | 53 |
| test.c:44:12:44:16 | ... > ... | true | 45 | 45 |
| test.c:44:12:44:16 | ... > ... | true | 45 | 47 |
| test.c:45:16:45:20 | ... > ... | true | 45 | 47 |
| test.c:58:9:58:14 | ... == ... | false | 58 | 58 |
| test.c:58:9:58:14 | ... == ... | false | 62 | 62 |
| test.c:58:9:58:23 | ... \|\| ... | false | 62 | 62 |
| test.c:58:19:58:23 | ... < ... | false | 62 | 62 |
| test.c:75:9:75:14 | ... == ... | false | 78 | 79 |
| test.c:75:9:75:14 | ... == ... | true | 75 | 77 |
| test.c:85:8:85:13 | ... == ... | true | 85 | 85 |
| test.c:85:8:85:13 | ... == ... | true | 86 | 86 |
| test.c:85:8:85:23 | ... && ... | true | 86 | 86 |
| test.c:85:18:85:23 | ... != ... | true | 86 | 86 |
| test.c:94:11:94:16 | ... != ... | false | 70 | 70 |
| test.c:94:11:94:16 | ... != ... | false | 99 | 102 |
| test.c:94:11:94:16 | ... != ... | false | 102 | 102 |
| test.c:94:11:94:16 | ... != ... | false | 107 | 109 |
| test.c:94:11:94:16 | ... != ... | false | 109 | 109 |
| test.c:94:11:94:16 | ... != ... | false | 109 | 117 |
| test.c:94:11:94:16 | ... != ... | false | 113 | 113 |
| test.c:94:11:94:16 | ... != ... | true | 94 | 96 |
| test.c:102:16:102:21 | ... < ... | false | 70 | 70 |
| test.c:102:16:102:21 | ... < ... | false | 107 | 109 |
| test.c:102:16:102:21 | ... < ... | false | 109 | 109 |
| test.c:102:16:102:21 | ... < ... | false | 109 | 117 |
| test.c:102:16:102:21 | ... < ... | false | 113 | 113 |
| test.c:102:16:102:21 | ... < ... | true | 102 | 102 |
| test.c:109:9:109:14 | ... == ... | false | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | false | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | false | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | false | 113 | 113 |
| test.c:126:7:126:7 | 1 | true | 126 | 126 |
| test.c:126:7:126:7 | 1 | true | 126 | 128 |
| test.c:126:7:126:7 | 1 | true | 131 | 131 |
| test.c:126:7:126:7 | 1 | true | 131 | 132 |
| test.c:126:7:126:7 | 1 | true | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | true | 126 | 128 |
| test.c:126:12:126:26 | call to test3_condition | true | 126 | 128 |
| test.c:131:7:131:7 | b | true | 131 | 132 |
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
| test.c:146:8:146:8 | x | false | 146 | 147 |
| test.c:152:8:152:8 | p | true | 152 | 154 |
| test.c:158:8:158:9 | ! ... | true | 158 | 160 |
| test.c:158:9:158:9 | p | false | 158 | 160 |
| test.c:164:8:164:8 | s | true | 164 | 166 |
| test.c:170:8:170:9 | ! ... | true | 170 | 172 |
| test.c:170:9:170:9 | s | false | 170 | 172 |
| test.c:176:8:176:15 | ! ... | true | 176 | 178 |
| test.c:176:10:176:14 | ... < ... | false | 176 | 178 |
| test.c:182:8:182:34 | ! ... | true | 182 | 184 |
| test.c:182:10:182:20 | ... >= ... | true | 181 | 182 |
| test.c:182:10:182:20 | ... >= ... | true | 182 | 182 |
| test.c:182:10:182:33 | ... && ... | false | 182 | 184 |
| test.c:182:10:182:33 | ... && ... | true | 181 | 182 |
| test.c:182:25:182:33 | ... < ... | true | 181 | 182 |
| test.c:190:7:190:8 | ! ... | true | 190 | 192 |
| test.c:190:8:190:8 | c | false | 190 | 192 |
| test.c:198:7:198:8 | ! ... | true | 198 | 200 |
| test.c:198:8:198:8 | b | false | 198 | 200 |
| test.c:206:7:206:8 | ! ... | true | 206 | 208 |
| test.c:206:8:206:8 | c | false | 206 | 208 |
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | true | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | true | 31 | 32 |
| test.cpp:42:13:42:20 | call to getABool | true | 43 | 45 |
| test.cpp:61:10:61:10 | i | Case[0] | 62 | 64 |
| test.cpp:61:10:61:10 | i | Case[1] | 65 | 66 |
| test.cpp:74:10:74:10 | i | Case[0..10] | 75 | 77 |
| test.cpp:74:10:74:10 | i | Case[11..20] | 78 | 79 |
| test.cpp:93:6:93:6 | c | true | 93 | 94 |
| test.cpp:99:6:99:6 | f | true | 99 | 100 |
| test.cpp:105:6:105:14 | ... != ... | true | 105 | 106 |
| test.cpp:111:6:111:14 | ... != ... | true | 111 | 112 |
| test.cpp:122:9:122:9 | b | true | 123 | 125 |
| test.cpp:122:9:122:9 | b | true | 125 | 125 |
| test.cpp:125:13:125:20 | ! ... | true | 125 | 125 |
| test.cpp:125:14:125:17 | call to safe | false | 125 | 125 |
| test.cpp:131:6:131:21 | call to __builtin_expect | true | 131 | 132 |
| test.cpp:135:6:135:21 | call to __builtin_expect | true | 135 | 136 |
| test.cpp:141:6:141:21 | call to __builtin_expect | true | 141 | 142 |
| test.cpp:145:6:145:21 | call to __builtin_expect | true | 145 | 146 |
| test.cpp:152:7:152:8 | ! ... | true | 152 | 153 |
| test.cpp:152:8:152:8 | b | false | 152 | 153 |
| test.cpp:160:7:160:8 | ! ... | true | 160 | 162 |
| test.cpp:160:8:160:8 | c | false | 160 | 162 |
| test.cpp:168:7:168:8 | ! ... | true | 168 | 170 |
| test.cpp:168:8:168:8 | b | false | 168 | 170 |
| test.cpp:176:7:176:8 | ! ... | true | 176 | 178 |
| test.cpp:176:8:176:8 | c | false | 176 | 178 |
| test.cpp:182:6:182:16 | ! ... | false | 185 | 188 |
| test.cpp:182:6:182:16 | ! ... | true | 182 | 184 |
| test.cpp:182:8:182:9 | b1 | true | 181 | 182 |
| test.cpp:182:8:182:9 | b1 | true | 182 | 182 |
| test.cpp:182:8:182:15 | ... && ... | false | 182 | 184 |
| test.cpp:182:8:182:15 | ... && ... | true | 181 | 182 |
| test.cpp:182:8:182:15 | ... && ... | true | 185 | 188 |
| test.cpp:182:14:182:15 | b2 | true | 181 | 182 |
| test.cpp:193:6:193:16 | ! ... | false | 197 | 199 |
| test.cpp:193:6:193:16 | ! ... | true | 193 | 196 |
| test.cpp:193:8:193:9 | b1 | false | 192 | 193 |
| test.cpp:193:8:193:9 | b1 | false | 193 | 193 |
| test.cpp:193:8:193:15 | ... \|\| ... | false | 192 | 193 |
| test.cpp:193:8:193:15 | ... \|\| ... | false | 193 | 196 |
| test.cpp:193:8:193:15 | ... \|\| ... | true | 197 | 199 |
| test.cpp:193:14:193:15 | b2 | false | 192 | 193 |
| test.cpp:211:9:211:15 | ... == ... | true | 211 | 212 |
| test.cpp:214:9:214:17 | ... == ... | true | 214 | 215 |
| test.cpp:217:9:217:15 | ... == ... | true | 217 | 218 |
| test.cpp:220:9:220:14 | ... == ... | true | 220 | 221 |
| test.cpp:223:9:223:16 | ... == ... | true | 223 | 224 |
| test.cpp:226:9:226:14 | ... == ... | true | 226 | 227 |
| test.cpp:229:9:229:14 | ... == ... | true | 229 | 230 |
| test.cpp:232:9:232:18 | ... == ... | true | 232 | 233 |
| test.cpp:235:9:235:17 | ... == ... | true | 235 | 236 |
| test.cpp:238:9:238:17 | ... == ... | true | 238 | 239 |
| test.cpp:241:9:241:17 | ... == ... | true | 241 | 241 |
| test.cpp:241:9:241:17 | ... == ... | true | 241 | 242 |
| test.cpp:241:9:241:30 | ... && ... | true | 241 | 241 |
| test.cpp:241:9:241:30 | ... && ... | true | 241 | 242 |
| test.cpp:241:9:241:43 | ... && ... | true | 241 | 242 |
| test.cpp:241:22:241:30 | ... == ... | true | 241 | 241 |
| test.cpp:241:22:241:30 | ... == ... | true | 241 | 242 |
| test.cpp:241:35:241:43 | ... == ... | true | 241 | 242 |
| test.c:7:9:7:13 | ... > ... | false | test.c:10:12:11:14 | { ... } |
| test.c:7:9:7:13 | ... > ... | true | test.c:7:16:9:14 | { ... } |
| test.c:17:8:17:12 | ... < ... | true | test.c:17:17:17:21 | y |
| test.c:17:8:17:12 | ... < ... | true | test.c:18:9:18:14 | ExprStmt |
| test.c:17:8:17:21 | ... && ... | true | test.c:18:9:18:14 | ExprStmt |
| test.c:17:17:17:21 | ... > ... | true | test.c:18:9:18:14 | ExprStmt |
| test.c:26:11:26:15 | ... > ... | false | test.c:2:5:2:8 | test |
| test.c:26:11:26:15 | ... > ... | false | test.c:31:5:34:13 | ExprStmt |
| test.c:26:11:26:15 | ... > ... | false | test.c:34:16:34:21 | j |
| test.c:26:11:26:15 | ... > ... | false | test.c:34:29:34:26 | { ... } |
| test.c:26:11:26:15 | ... > ... | false | test.c:39:5:42:13 | ExprStmt |
| test.c:26:11:26:15 | ... > ... | false | test.c:42:5:42:26 | label ...: |
| test.c:26:11:26:15 | ... > ... | false | test.c:42:16:42:21 | j |
| test.c:26:11:26:15 | ... > ... | false | test.c:42:29:44:16 | { ... } |
| test.c:26:11:26:15 | ... > ... | false | test.c:45:13:45:20 | if (...) ... |
| test.c:26:11:26:15 | ... > ... | false | test.c:45:23:47:22 | { ... } |
| test.c:26:11:26:15 | ... > ... | false | test.c:51:14:53:21 | { ... } |
| test.c:26:11:26:15 | ... > ... | false | test.c:56:5:58:14 | label ...: |
| test.c:26:11:26:15 | ... > ... | false | test.c:58:19:58:23 | y |
| test.c:26:11:26:15 | ... > ... | false | test.c:58:26:66:12 | { ... } |
| test.c:26:11:26:15 | ... > ... | false | test.c:62:9:62:16 | return ... |
| test.c:26:11:26:15 | ... > ... | true | test.c:26:18:28:11 | { ... } |
| test.c:34:16:34:21 | ... < ... | false | test.c:2:5:2:8 | test |
| test.c:34:16:34:21 | ... < ... | false | test.c:39:5:42:13 | ExprStmt |
| test.c:34:16:34:21 | ... < ... | false | test.c:42:5:42:26 | label ...: |
| test.c:34:16:34:21 | ... < ... | false | test.c:42:16:42:21 | j |
| test.c:34:16:34:21 | ... < ... | false | test.c:42:29:44:16 | { ... } |
| test.c:34:16:34:21 | ... < ... | false | test.c:45:13:45:20 | if (...) ... |
| test.c:34:16:34:21 | ... < ... | false | test.c:45:23:47:22 | { ... } |
| test.c:34:16:34:21 | ... < ... | false | test.c:51:14:53:21 | { ... } |
| test.c:34:16:34:21 | ... < ... | false | test.c:56:5:58:14 | label ...: |
| test.c:34:16:34:21 | ... < ... | false | test.c:58:19:58:23 | y |
| test.c:34:16:34:21 | ... < ... | false | test.c:58:26:66:12 | { ... } |
| test.c:34:16:34:21 | ... < ... | false | test.c:62:9:62:16 | return ... |
| test.c:34:16:34:21 | ... < ... | true | test.c:34:29:34:26 | { ... } |
| test.c:42:16:42:21 | ... < ... | true | test.c:42:5:42:26 | label ...: |
| test.c:42:16:42:21 | ... < ... | true | test.c:42:29:44:16 | { ... } |
| test.c:42:16:42:21 | ... < ... | true | test.c:45:13:45:20 | if (...) ... |
| test.c:42:16:42:21 | ... < ... | true | test.c:45:23:47:22 | { ... } |
| test.c:42:16:42:21 | ... < ... | true | test.c:51:14:53:21 | { ... } |
| test.c:44:12:44:16 | ... > ... | false | test.c:42:5:42:26 | label ...: |
| test.c:44:12:44:16 | ... > ... | false | test.c:51:14:53:21 | { ... } |
| test.c:44:12:44:16 | ... > ... | true | test.c:45:13:45:20 | if (...) ... |
| test.c:44:12:44:16 | ... > ... | true | test.c:45:23:47:22 | { ... } |
| test.c:45:16:45:20 | ... > ... | true | test.c:45:23:47:22 | { ... } |
| test.c:58:9:58:14 | ... == ... | false | test.c:58:19:58:23 | y |
| test.c:58:9:58:14 | ... == ... | false | test.c:62:9:62:16 | return ... |
| test.c:58:9:58:23 | ... \|\| ... | false | test.c:62:9:62:16 | return ... |
| test.c:58:19:58:23 | ... < ... | false | test.c:62:9:62:16 | return ... |
| test.c:75:9:75:14 | ... == ... | false | test.c:78:12:79:14 | { ... } |
| test.c:75:9:75:14 | ... == ... | true | test.c:75:17:77:14 | { ... } |
| test.c:85:8:85:13 | ... == ... | true | test.c:85:18:85:23 | y |
| test.c:85:8:85:13 | ... == ... | true | test.c:86:9:86:14 | ExprStmt |
| test.c:85:8:85:23 | ... && ... | true | test.c:86:9:86:14 | ExprStmt |
| test.c:85:18:85:23 | ... != ... | true | test.c:86:9:86:14 | ExprStmt |
| test.c:94:11:94:16 | ... != ... | false | test.c:70:5:70:9 | test2 |
| test.c:94:11:94:16 | ... != ... | false | test.c:99:5:102:13 | ExprStmt |
| test.c:94:11:94:16 | ... != ... | false | test.c:102:16:102:21 | j |
| test.c:94:11:94:16 | ... != ... | false | test.c:102:29:102:26 | { ... } |
| test.c:94:11:94:16 | ... != ... | false | test.c:107:5:109:14 | ExprStmt |
| test.c:94:11:94:16 | ... != ... | false | test.c:109:19:109:23 | y |
| test.c:94:11:94:16 | ... != ... | false | test.c:109:26:117:12 | { ... } |
| test.c:94:11:94:16 | ... != ... | false | test.c:113:9:113:16 | return ... |
| test.c:94:11:94:16 | ... != ... | true | test.c:94:19:96:11 | { ... } |
| test.c:102:16:102:21 | ... < ... | false | test.c:70:5:70:9 | test2 |
| test.c:102:16:102:21 | ... < ... | false | test.c:107:5:109:14 | ExprStmt |
| test.c:102:16:102:21 | ... < ... | false | test.c:109:19:109:23 | y |
| test.c:102:16:102:21 | ... < ... | false | test.c:109:26:117:12 | { ... } |
| test.c:102:16:102:21 | ... < ... | false | test.c:113:9:113:16 | return ... |
| test.c:102:16:102:21 | ... < ... | true | test.c:102:29:102:26 | { ... } |
| test.c:109:9:109:14 | ... == ... | false | test.c:109:19:109:23 | y |
| test.c:109:9:109:14 | ... == ... | false | test.c:113:9:113:16 | return ... |
| test.c:109:9:109:23 | ... \|\| ... | false | test.c:113:9:113:16 | return ... |
| test.c:109:19:109:23 | ... < ... | false | test.c:113:9:113:16 | return ... |
| test.c:126:7:126:7 | 1 | true | test.c:126:12:126:26 | call to test3_condition |
| test.c:126:7:126:7 | 1 | true | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:7 | 1 | true | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:7 | 1 | true | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:7 | 1 | true | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | true | test.c:126:31:128:16 | { ... } |
| test.c:126:12:126:26 | call to test3_condition | true | test.c:126:31:128:16 | { ... } |
| test.c:131:7:131:7 | b | true | test.c:131:10:132:16 | { ... } |
| test.c:137:7:137:7 | 0 | false | test.c:142:3:136:10 | return ... |
| test.c:146:7:146:8 | ! ... | true | test.c:146:11:147:9 | { ... } |
| test.c:146:8:146:8 | x | false | test.c:146:11:147:9 | { ... } |
| test.c:152:8:152:8 | p | true | test.c:152:11:154:5 | { ... } |
| test.c:158:8:158:9 | ! ... | true | test.c:158:12:160:5 | { ... } |
| test.c:158:9:158:9 | p | false | test.c:158:12:160:5 | { ... } |
| test.c:164:8:164:8 | s | true | test.c:164:11:166:5 | { ... } |
| test.c:170:8:170:9 | ! ... | true | test.c:170:12:172:5 | { ... } |
| test.c:170:9:170:9 | s | false | test.c:170:12:172:5 | { ... } |
| test.c:176:8:176:15 | ! ... | true | test.c:176:18:178:5 | { ... } |
| test.c:176:10:176:14 | ... < ... | false | test.c:176:18:178:5 | { ... } |
| test.c:182:8:182:34 | ! ... | true | test.c:182:37:184:5 | { ... } |
| test.c:182:10:182:20 | ... >= ... | true | test.c:181:25:182:20 | { ... } |
| test.c:182:10:182:20 | ... >= ... | true | test.c:182:25:182:33 | foo |
| test.c:182:10:182:33 | ... && ... | false | test.c:182:37:184:5 | { ... } |
| test.c:182:10:182:33 | ... && ... | true | test.c:181:25:182:20 | { ... } |
| test.c:182:25:182:33 | ... < ... | true | test.c:181:25:182:20 | { ... } |
| test.c:190:7:190:8 | ! ... | true | test.c:190:11:192:3 | { ... } |
| test.c:190:8:190:8 | c | false | test.c:190:11:192:3 | { ... } |
| test.c:198:7:198:8 | ! ... | true | test.c:198:11:200:3 | { ... } |
| test.c:198:8:198:8 | b | false | test.c:198:11:200:3 | { ... } |
| test.c:206:7:206:8 | ! ... | true | test.c:206:11:208:3 | { ... } |
| test.c:206:8:206:8 | c | false | test.c:206:11:208:3 | { ... } |
| test.c:215:6:215:18 | call to __builtin_expect | true | test.c:215:21:217:5 | { ... } |
| test.c:219:9:219:22 | call to __builtin_expect | true | test.c:219:25:221:5 | { ... } |
| test.cpp:18:8:18:10 | call to get | true | test.cpp:19:5:19:14 | ExprStmt |
| test.cpp:31:7:31:13 | ... == ... | false | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | false | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | true | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | true | test.cpp:31:16:32:21 | { ... } |
| test.cpp:42:13:42:20 | call to getABool | true | test.cpp:43:9:45:23 | { ... } |
| test.cpp:61:10:61:10 | i | Case[0] | test.cpp:62:5:64:12 | case ...: |
| test.cpp:61:10:61:10 | i | Case[1] | test.cpp:65:5:66:10 | case ...: |
| test.cpp:74:10:74:10 | i | Case[0..10] | test.cpp:75:5:77:12 | case ...: |
| test.cpp:74:10:74:10 | i | Case[11..20] | test.cpp:78:5:79:10 | case ...: |
| test.cpp:93:6:93:6 | c | true | test.cpp:93:9:94:7 | { ... } |
| test.cpp:99:6:99:6 | f | true | test.cpp:99:9:100:7 | { ... } |
| test.cpp:105:6:105:14 | ... != ... | true | test.cpp:105:17:106:7 | { ... } |
| test.cpp:111:6:111:14 | ... != ... | true | test.cpp:111:17:112:7 | { ... } |
| test.cpp:122:9:122:9 | b | true | test.cpp:123:5:125:20 | { ... } |
| test.cpp:122:9:122:9 | b | true | test.cpp:125:23:125:29 | return ... |
| test.cpp:125:13:125:20 | ! ... | true | test.cpp:125:23:125:29 | return ... |
| test.cpp:125:14:125:17 | call to safe | false | test.cpp:125:23:125:29 | return ... |
| test.cpp:131:6:131:21 | call to __builtin_expect | true | test.cpp:131:40:132:9 | { ... } |
| test.cpp:135:6:135:21 | call to __builtin_expect | true | test.cpp:135:40:136:9 | { ... } |
| test.cpp:141:6:141:21 | call to __builtin_expect | true | test.cpp:141:36:142:9 | { ... } |
| test.cpp:145:6:145:21 | call to __builtin_expect | true | test.cpp:145:36:146:9 | { ... } |
| test.cpp:152:7:152:8 | ! ... | true | test.cpp:152:11:153:9 | { ... } |
| test.cpp:152:8:152:8 | b | false | test.cpp:152:11:153:9 | { ... } |
| test.cpp:160:7:160:8 | ! ... | true | test.cpp:160:11:162:3 | { ... } |
| test.cpp:160:8:160:8 | c | false | test.cpp:160:11:162:3 | { ... } |
| test.cpp:168:7:168:8 | ! ... | true | test.cpp:168:11:170:3 | { ... } |
| test.cpp:168:8:168:8 | b | false | test.cpp:168:11:170:3 | { ... } |
| test.cpp:176:7:176:8 | ! ... | true | test.cpp:176:11:178:3 | { ... } |
| test.cpp:176:8:176:8 | c | false | test.cpp:176:11:178:3 | { ... } |
| test.cpp:182:6:182:16 | ! ... | false | test.cpp:185:10:188:7 | { ... } |
| test.cpp:182:6:182:16 | ! ... | true | test.cpp:182:19:184:7 | { ... } |
| test.cpp:182:8:182:9 | b1 | true | test.cpp:181:41:182:9 | { ... } |
| test.cpp:182:8:182:9 | b1 | true | test.cpp:182:14:182:15 | b2 |
| test.cpp:182:8:182:15 | ... && ... | false | test.cpp:182:19:184:7 | { ... } |
| test.cpp:182:8:182:15 | ... && ... | true | test.cpp:181:41:182:9 | { ... } |
| test.cpp:182:8:182:15 | ... && ... | true | test.cpp:185:10:188:7 | { ... } |
| test.cpp:182:14:182:15 | b2 | true | test.cpp:181:41:182:9 | { ... } |
| test.cpp:193:6:193:16 | ! ... | false | test.cpp:197:10:199:7 | { ... } |
| test.cpp:193:6:193:16 | ! ... | true | test.cpp:193:19:196:7 | { ... } |
| test.cpp:193:8:193:9 | b1 | false | test.cpp:192:40:193:9 | { ... } |
| test.cpp:193:8:193:9 | b1 | false | test.cpp:193:14:193:15 | b2 |
| test.cpp:193:8:193:15 | ... \|\| ... | false | test.cpp:192:40:193:9 | { ... } |
| test.cpp:193:8:193:15 | ... \|\| ... | false | test.cpp:193:19:196:7 | { ... } |
| test.cpp:193:8:193:15 | ... \|\| ... | true | test.cpp:197:10:199:7 | { ... } |
| test.cpp:193:14:193:15 | b2 | false | test.cpp:192:40:193:9 | { ... } |
| test.cpp:211:9:211:15 | ... == ... | true | test.cpp:211:18:212:13 | { ... } |
| test.cpp:214:9:214:17 | ... == ... | true | test.cpp:214:20:215:13 | { ... } |
| test.cpp:217:9:217:15 | ... == ... | true | test.cpp:217:18:218:13 | { ... } |
| test.cpp:220:9:220:14 | ... == ... | true | test.cpp:220:17:221:13 | { ... } |
| test.cpp:223:9:223:16 | ... == ... | true | test.cpp:223:19:224:13 | { ... } |
| test.cpp:226:9:226:14 | ... == ... | true | test.cpp:226:17:227:13 | { ... } |
| test.cpp:229:9:229:14 | ... == ... | true | test.cpp:229:17:230:13 | { ... } |
| test.cpp:232:9:232:18 | ... == ... | true | test.cpp:232:21:233:13 | { ... } |
| test.cpp:235:9:235:17 | ... == ... | true | test.cpp:235:20:236:13 | { ... } |
| test.cpp:238:9:238:17 | ... == ... | true | test.cpp:238:20:239:13 | { ... } |
| test.cpp:241:9:241:17 | ... == ... | true | test.cpp:241:22:241:30 | ms |
| test.cpp:241:9:241:17 | ... == ... | true | test.cpp:241:35:241:43 | ms |
| test.cpp:241:9:241:17 | ... == ... | true | test.cpp:241:46:242:13 | { ... } |
| test.cpp:241:9:241:30 | ... && ... | true | test.cpp:241:35:241:43 | ms |
| test.cpp:241:9:241:30 | ... && ... | true | test.cpp:241:46:242:13 | { ... } |
| test.cpp:241:9:241:43 | ... && ... | true | test.cpp:241:46:242:13 | { ... } |
| test.cpp:241:22:241:30 | ... == ... | true | test.cpp:241:35:241:43 | ms |
| test.cpp:241:22:241:30 | ... == ... | true | test.cpp:241:46:242:13 | { ... } |
| test.cpp:241:35:241:43 | ... == ... | true | test.cpp:241:46:242:13 | { ... } |
| test.cpp:247:6:247:18 | ... == ... | false | test.cpp:249:10:251:3 | { ... } |
| test.cpp:247:6:247:18 | ... == ... | true | test.cpp:247:21:249:3 | { ... } |
| test.cpp:253:6:253:18 | ... != ... | false | test.cpp:255:10:257:3 | { ... } |
| test.cpp:253:6:253:18 | ... != ... | true | test.cpp:253:21:255:3 | { ... } |
| test.cpp:260:6:260:18 | ... == ... | false | test.cpp:262:10:264:3 | { ... } |
| test.cpp:260:6:260:18 | ... == ... | true | test.cpp:260:21:262:3 | { ... } |
| test.cpp:266:6:266:18 | ... != ... | false | test.cpp:268:10:270:3 | { ... } |
| test.cpp:266:6:266:18 | ... != ... | true | test.cpp:266:21:268:3 | { ... } |
| test.cpp:273:6:273:17 | ... == ... | false | test.cpp:275:10:277:3 | { ... } |
| test.cpp:273:6:273:17 | ... == ... | true | test.cpp:273:20:275:3 | { ... } |
| test.cpp:279:6:279:17 | ... != ... | false | test.cpp:281:10:283:3 | { ... } |
| test.cpp:279:6:279:17 | ... != ... | true | test.cpp:279:20:281:3 | { ... } |
| test.cpp:287:6:287:19 | ... == ... | false | test.cpp:289:10:291:3 | { ... } |
| test.cpp:287:6:287:19 | ... == ... | true | test.cpp:287:22:289:3 | { ... } |
| test.cpp:293:6:293:19 | ... != ... | false | test.cpp:295:10:297:3 | { ... } |
| test.cpp:293:6:293:19 | ... != ... | true | test.cpp:293:22:295:3 | { ... } |
| test.cpp:300:6:300:19 | ... == ... | false | test.cpp:302:10:304:3 | { ... } |
| test.cpp:300:6:300:19 | ... == ... | true | test.cpp:300:22:302:3 | { ... } |
| test.cpp:306:6:306:19 | ... != ... | false | test.cpp:308:10:310:3 | { ... } |
| test.cpp:306:6:306:19 | ... != ... | true | test.cpp:306:22:308:3 | { ... } |
| test.cpp:312:6:312:18 | ... == ... | false | test.cpp:314:10:316:3 | { ... } |
| test.cpp:312:6:312:18 | ... == ... | true | test.cpp:312:21:314:3 | { ... } |
| test.cpp:318:6:318:18 | ... != ... | false | test.cpp:320:10:322:3 | { ... } |
| test.cpp:318:6:318:18 | ... != ... | true | test.cpp:318:21:320:3 | { ... } |

View File

@@ -7,10 +7,6 @@
import cpp
import semmle.code.cpp.controlflow.Guards
from GuardCondition guard, AbstractValue value, int start, int end
where
exists(BasicBlock block |
guard.valueControls(block, value) and
block.hasLocationInfo(_, start, _, end, _)
)
select guard, value, start, end
from GuardCondition guard, AbstractValue value, BasicBlock block
where guard.valueControls(block, value)
select guard, value, block

View File

@@ -8,31 +8,23 @@ import cpp
import semmle.code.cpp.controlflow.Guards
query predicate binary(
GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end
GuardCondition guard, Expr left, string op, Expr right, int k, BasicBlock block
) {
exists(BasicBlock block |
guard.ensuresLt(left, right, k, block, true) and op = "<"
or
guard.ensuresLt(left, right, k, block, false) and op = ">="
or
guard.ensuresEq(left, right, k, block, true) and op = "=="
or
guard.ensuresEq(left, right, k, block, false) and op = "!="
|
block.hasLocationInfo(_, start, _, end, _)
)
guard.ensuresLt(left, right, k, block, true) and op = "<"
or
guard.ensuresLt(left, right, k, block, false) and op = ">="
or
guard.ensuresEq(left, right, k, block, true) and op = "=="
or
guard.ensuresEq(left, right, k, block, false) and op = "!="
}
query predicate unary(GuardCondition guard, Expr left, string op, int k, int start, int end) {
exists(BasicBlock block |
guard.ensuresLt(left, k, block, true) and op = "<"
or
guard.ensuresLt(left, k, block, false) and op = ">="
or
guard.ensuresEq(left, k, block, true) and op = "=="
or
guard.ensuresEq(left, k, block, false) and op = "!="
|
block.hasLocationInfo(_, start, _, end, _)
)
query predicate unary(GuardCondition guard, Expr left, string op, int k, BasicBlock block) {
guard.ensuresLt(left, k, block, true) and op = "<"
or
guard.ensuresLt(left, k, block, false) and op = ">="
or
guard.ensuresEq(left, k, block, true) and op = "=="
or
guard.ensuresEq(left, k, block, false) and op = "!="
}

View File

@@ -206,4 +206,17 @@ void test14(int a, int b) {
if (!c) {
}
}
}
# define likely(x) __builtin_expect(!!(x), 1)
void test15(int a, int b)
{
if (likely(a > b)) {
}
if (likely(a > 42)) {
}
}

View File

@@ -242,3 +242,82 @@ int test_types(signed char sc, unsigned long ul, float f, double d, bool b, Myst
ctr++;
}
}
void test_cmp_implies(int a, int b) {
if((a == b) == 0) {
} else {
}
if((a == b) != 0) {
} else {
}
if((a != b) == 0) {
} else {
}
if((a != b) != 0) {
} else {
}
if((a < b) == 0) {
} else {
}
if((a < b) != 0) {
} else {
}
}
void test_cmp_implies_unary(int a) {
if((a == 42) == 0) {
} else {
}
if((a == 42) != 0) {
} else {
}
if((a != 42) == 0) {
} else {
}
if((a != 42) != 0) {
} else {
}
if((a < 42) == 0) {
} else {
}
if((a < 42) != 0) {
} else {
}
}

View File

@@ -1,4 +1,5 @@
edges
| test.c:10:31:10:32 | sscanf output argument | test.c:11:7:11:7 | x | provenance | |
| test.cpp:34:15:34:16 | scanf output argument | test.cpp:35:7:35:7 | i | provenance | |
| test.cpp:41:19:41:20 | scanf output argument | test.cpp:43:8:43:8 | i | provenance | |
| test.cpp:58:19:58:20 | scanf output argument | test.cpp:60:8:60:8 | i | provenance | |
@@ -56,6 +57,8 @@ edges
| test.cpp:567:35:567:36 | scanf output argument | test.cpp:569:9:569:9 | i | provenance | |
| test.cpp:575:30:575:31 | scanf output argument | test.cpp:577:9:577:9 | i | provenance | |
nodes
| test.c:10:31:10:32 | sscanf output argument | semmle.label | sscanf output argument |
| test.c:11:7:11:7 | x | semmle.label | x |
| test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument |
| test.cpp:35:7:35:7 | i | semmle.label | i |
| test.cpp:41:19:41:20 | scanf output argument | semmle.label | scanf output argument |
@@ -186,5 +189,3 @@ subpaths
| test.cpp:484:9:484:9 | i | test.cpp:480:25:480:26 | scanf output argument | test.cpp:484:9:484:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:480:13:480:17 | call to scanf | call to scanf |
| test.cpp:495:8:495:8 | i | test.cpp:491:25:491:26 | scanf output argument | test.cpp:495:8:495:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:491:13:491:17 | call to scanf | call to scanf |
| test.cpp:545:8:545:8 | f | test.cpp:541:43:541:44 | sscanf output argument | test.cpp:545:8:545:8 | f | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 3. | test.cpp:541:10:541:15 | call to sscanf | call to sscanf |
| test.cpp:569:9:569:9 | i | test.cpp:567:35:567:36 | scanf output argument | test.cpp:569:9:569:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:567:23:567:27 | call to scanf | call to scanf |
| test.cpp:577:9:577:9 | i | test.cpp:575:30:575:31 | scanf output argument | test.cpp:577:9:577:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:575:18:575:22 | call to scanf | call to scanf |

View File

@@ -0,0 +1,13 @@
# define likely(x) __builtin_expect(!!(x), 1)
int sscanf(const char *s, const char *format, ...);
void use(int i);
void test_likely(const char* s, const char* format)
{
int x;
if (likely(sscanf(s, format, &x) == 1)) {
use(x); // GOOD
}
}

View File

@@ -566,7 +566,7 @@ void test_scanf_compared_in_conjunct_right(bool b) {
int i;
bool success = b && scanf("%d", &i) == 1;
if(success) {
use(i); // GOOD [FALSE POSITIVE]
use(i); // GOOD
}
}
@@ -574,6 +574,6 @@ void test_scanf_compared_in_conjunct_left(bool b) {
int i;
bool success = scanf("%d", &i) == 1 && b;
if(success) {
use(i); // GOOD [FALSE POSITIVE]
use(i); // GOOD
}
}

View File

@@ -6,3 +6,4 @@
| test.cpp:83:7:83:40 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:78:16:78:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
| test.cpp:87:7:87:38 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:7:57:7:77 | call to SSL_get_verify_result | call to SSL_get_verify_result |
| test.cpp:107:13:107:42 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:105:16:105:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
| test.cpp:109:7:109:8 | ok | This expression conflates OK and non-OK results from $@. | test.cpp:105:16:105:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |