Skip to content

Commit be359a3

Browse files
authored
Merge pull request #11976 from MathiasVP/fewer-uses-2
C++: Don't count every conversion as a use
2 parents 22202af + 7cc7675 commit be359a3

18 files changed

Lines changed: 42 additions & 312 deletions

File tree

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ class ReturnIndirectionNode extends IndirectReturnNode, ReturnNode {
370370
private Operand fullyConvertedCallStep(Operand op) {
371371
not exists(getANonConversionUse(op)) and
372372
exists(Instruction instr |
373-
conversionFlow(op, instr, _) and
373+
conversionFlow(op, instr, _, _) and
374374
result = getAUse(instr)
375375
)
376376
}
@@ -397,7 +397,7 @@ Operand getAUse(Instruction instr) {
397397
*/
398398
private Instruction getANonConversionUse(Operand operand) {
399399
result = getUse(operand) and
400-
not conversionFlow(_, result, _)
400+
not conversionFlow(_, result, _, _)
401401
}
402402

403403
/**
@@ -555,7 +555,7 @@ private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand opera
555555
or
556556
exists(Operand op, Instruction instr |
557557
instr = op.getDef() and
558-
conversionFlow(operandFrom, instr, _) and
558+
conversionFlow(operandFrom, instr, _, _) and
559559
numberOfLoadsFromOperand(op, operandTo, ind)
560560
)
561561
}
@@ -568,7 +568,7 @@ private predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandT
568568
numberOfLoadsFromOperandRec(operandFrom, operandTo, n)
569569
or
570570
not Ssa::isDereference(_, operandFrom) and
571-
not conversionFlow(operandFrom, _, _) and
571+
not conversionFlow(operandFrom, _, _, _) and
572572
operandFrom = operandTo and
573573
n = 0
574574
}

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,32 @@ class FieldAddress extends Operand {
7777
*
7878
* `isPointerArith` is `true` if `instrTo` is a `PointerArithmeticInstruction` and `opFrom`
7979
* is the left operand.
80+
*
81+
* `additional` is `true` if the conversion is supplied by an implementation of the
82+
* `Indirection` class. It is sometimes useful to exclude such conversions.
8083
*/
81-
predicate conversionFlow(Operand opFrom, Instruction instrTo, boolean isPointerArith) {
84+
predicate conversionFlow(
85+
Operand opFrom, Instruction instrTo, boolean isPointerArith, boolean additional
86+
) {
8287
isPointerArith = false and
8388
(
84-
instrTo.(CopyValueInstruction).getSourceValueOperand() = opFrom
85-
or
86-
instrTo.(ConvertInstruction).getUnaryOperand() = opFrom
87-
or
88-
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
89-
or
90-
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
89+
additional = false and
90+
(
91+
instrTo.(CopyValueInstruction).getSourceValueOperand() = opFrom
92+
or
93+
instrTo.(ConvertInstruction).getUnaryOperand() = opFrom
94+
or
95+
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
96+
or
97+
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
98+
)
9199
or
100+
additional = true and
92101
Ssa::isAdditionalConversionFlow(opFrom, instrTo)
93102
)
94103
or
95104
isPointerArith = true and
105+
additional = false and
96106
instrTo.(PointerArithmeticInstruction).getLeftOperand() = opFrom
97107
}
98108

@@ -1365,7 +1375,7 @@ private module Cached {
13651375

13661376
private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) {
13671377
// Treat all conversions as flow, even conversions between different numeric types.
1368-
conversionFlow(opFrom, iTo, false)
1378+
conversionFlow(opFrom, iTo, false, _)
13691379
or
13701380
iTo.(CopyInstruction).getSourceValueOperand() = opFrom
13711381
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
469469
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
470470
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
471471
instr = op2.getDef() and
472-
conversionFlow(op1, instr, _)
472+
conversionFlow(op1, instr, _, _)
473473
)
474474
}
475475

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ private module IteratorIndirections {
208208

209209
override predicate isAdditionalDereference(Instruction deref, Operand address) {
210210
exists(CallInstruction call |
211-
operandForfullyConvertedCall(deref.getAUse(), call) and
211+
operandForfullyConvertedCall(getAUse(deref), call) and
212212
this = call.getStaticCallTarget().getClassAndName("operator*") and
213213
address = call.getThisArgumentOperand()
214214
)
@@ -586,6 +586,15 @@ private module Cached {
586586
)
587587
}
588588

589+
/** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
590+
private predicate isConversion(Operand op) {
591+
exists(Instruction def, Operand use |
592+
def = op.getDef() and
593+
use = unique( | | getAUse(def)) and
594+
conversionFlow(use, _, false, false)
595+
)
596+
}
597+
589598
/**
590599
* Holds if `op` is a use of an SSA variable rooted at `base` with `ind` number
591600
* of indirections.
@@ -603,6 +612,9 @@ private module Cached {
603612
type = getLanguageType(op) and
604613
upper = countIndirectionsForCppType(type) and
605614
isUseImpl(op, base, ind0) and
615+
// Don't count every conversion as their own use. Instead, only the first
616+
// use (i.e., before any conversions are applied) will count as a use.
617+
not isConversion(op) and
606618
ind = ind0 + [0 .. upper] and
607619
indirectionIndex = ind - ind0
608620
)
@@ -653,7 +665,7 @@ private module Cached {
653665
exists(Operand mid, Instruction instr |
654666
isUseImpl(mid, base, ind) and
655667
instr = operand.getDef() and
656-
conversionFlow(mid, instr, false)
668+
conversionFlow(mid, instr, false, _)
657669
)
658670
or
659671
exists(int ind0 |
@@ -723,7 +735,7 @@ private module Cached {
723735
exists(Operand mid, Instruction instr, boolean certain0, boolean isPointerArith |
724736
isDefImpl(mid, base, ind, certain0) and
725737
instr = operand.getDef() and
726-
conversionFlow(mid, instr, isPointerArith) and
738+
conversionFlow(mid, instr, isPointerArith, _) and
727739
if isPointerArith = true then certain = false else certain = certain0
728740
)
729741
or

cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ void following_pointers(
4848

4949
int stackArray[2] = { source(), source() };
5050
stackArray[0] = source();
51-
sink(stackArray); // $ ast ir ir=49:35 ir=50:19
51+
sink(stackArray); // $ ast ir
5252
}

cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,12 +533,12 @@ void test_set_through_const_pointer(int *e)
533533
}
534534

535535
void sink_then_source_1(int* p) {
536-
sink(*p); // $ SPURIOUS: ir=537:10 ir=547:9
536+
sink(*p); // $ ir // Flow from the unitialized x to the dereference.
537537
*p = source();
538538
}
539539

540540
void sink_then_source_2(int* p, int y) {
541-
sink(y); // $ SPURIOUS: ast ir=542:10 ir=551:9
541+
sink(y); // $ SPURIOUS: ast ir
542542
*p = source();
543543
}
544544

cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ edges
1313
| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | call to B [c] |
1414
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection |
1515
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection |
16-
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection |
17-
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection |
1816
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c |
1917
| A.cpp:48:12:48:18 | call to make indirection [c] | A.cpp:49:10:49:10 | b indirection [c] |
2018
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c |
@@ -907,7 +905,6 @@ nodes
907905
| A.cpp:41:15:41:21 | new | semmle.label | new |
908906
| A.cpp:41:15:41:21 | new | semmle.label | new |
909907
| A.cpp:43:10:43:12 | & ... indirection | semmle.label | & ... indirection |
910-
| A.cpp:43:10:43:12 | & ... indirection | semmle.label | & ... indirection |
911908
| A.cpp:47:12:47:18 | new | semmle.label | new |
912909
| A.cpp:48:12:48:18 | call to make indirection [c] | semmle.label | call to make indirection [c] |
913910
| A.cpp:48:20:48:20 | c | semmle.label | c |
@@ -1765,8 +1762,6 @@ subpaths
17651762
#select
17661763
| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new |
17671764
| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new |
1768-
| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new |
1769-
| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new |
17701765
| A.cpp:49:10:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:10:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
17711766
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
17721767
| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |

0 commit comments

Comments
 (0)