Skip to content

Commit 044ee9b

Browse files
committed
C++: Delete old iterator flow using memory edges.
1 parent 3b44b13 commit 044ee9b

File tree

2 files changed

+0
-276
lines changed

2 files changed

+0
-276
lines changed

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

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,6 @@ private newtype TDefOrUseImpl =
121121
// a function body.
122122
isGlobalDefImpl(v, f, _, indirectionIndex)
123123
} or
124-
TIteratorDef(
125-
Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex
126-
) {
127-
isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex)
128-
} or
129-
TIteratorUse(
130-
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
131-
) {
132-
isIteratorUse(container, iteratorAddress, _, indirectionIndex)
133-
} or
134124
TFinalParameterUse(Parameter p, int indirectionIndex) {
135125
underlyingTypeIsModifiableAt(p.getUnderlyingType(), indirectionIndex) and
136126
// Only create an SSA read for the final use of a parameter if there's
@@ -336,20 +326,6 @@ private class DirectDef extends OperandBasedDef, TDefImpl {
336326
override predicate isCertain() { isDef(true, _, address, base, _, ind) }
337327
}
338328

339-
private class IteratorDef extends OperandBasedDef, TIteratorDef {
340-
BaseSourceVariableInstruction container;
341-
342-
IteratorDef() { this = TIteratorDef(address, container, ind) }
343-
344-
override BaseSourceVariableInstruction getBase() { result = container }
345-
346-
override int getIndirection() { isIteratorDef(container, address, _, result, ind) }
347-
348-
override Node0Impl getValue() { isIteratorDef(container, address, result, _, _) }
349-
350-
override predicate isCertain() { none() }
351-
}
352-
353329
abstract class UseImpl extends DefOrUseImpl {
354330
int ind;
355331

@@ -418,16 +394,6 @@ private class DirectUse extends OperandBasedUse, TUseImpl {
418394
override Node getNode() { nodeHasOperand(result, operand, ind) }
419395
}
420396

421-
private class IteratorUse extends OperandBasedUse, TIteratorUse {
422-
IteratorUse() { this = TIteratorUse(operand, base, ind) }
423-
424-
override int getIndirection() { isIteratorUse(base, operand, result, ind) }
425-
426-
override predicate isCertain() { none() }
427-
428-
override Node getNode() { nodeHasOperand(result, operand, ind) }
429-
}
430-
431397
pragma[nomagic]
432398
private predicate finalParameterNodeHasParameterAndIndex(
433399
FinalParameterNode n, Parameter p, int indirectionIndex

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

Lines changed: 0 additions & 242 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,6 @@ private module IteratorIndirections {
246246
baseType = super.getValueType()
247247
}
248248

249-
override predicate isAdditionalDereference(Instruction deref, Operand address) {
250-
exists(CallInstruction call |
251-
operandForFullyConvertedCall(getAUse(deref), call) and
252-
this = call.getStaticCallTarget().getClassAndName("operator*") and
253-
address = call.getThisArgumentOperand()
254-
)
255-
}
256-
257249
override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) {
258250
exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() |
259251
this = call.getStaticCallTarget().getClassAndName("operator=") and
@@ -262,16 +254,6 @@ private module IteratorIndirections {
262254
)
263255
}
264256

265-
override predicate isAdditionalTaintStep(Node node1, Node node2) {
266-
exists(CallInstruction call |
267-
// Taint through `operator+=` and `operator-=` on iterators.
268-
call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and
269-
node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and
270-
node1.(IndirectOperand).hasOperandAndIndirectionIndex(call.getArgumentOperand(0), _) and
271-
node1.getType().getUnspecifiedType() = this
272-
)
273-
}
274-
275257
override predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
276258
// This is a bit annoying: Consider the following snippet:
277259
// ```
@@ -589,230 +571,6 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns
589571

590572
cached
591573
private module Cached {
592-
private import semmle.code.cpp.models.interfaces.Iterator as Interfaces
593-
private import semmle.code.cpp.models.implementations.Iterator as Iterator
594-
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
595-
596-
/**
597-
* Holds if `next` is a instruction with a memory result that potentially
598-
* updates the memory produced by `prev`.
599-
*/
600-
private predicate memorySucc(Instruction prev, Instruction next) {
601-
prev = next.(ChiInstruction).getTotal()
602-
or
603-
// Phi inputs can be inexact.
604-
prev = next.(PhiInstruction).getAnInputOperand().getAnyDef()
605-
or
606-
prev = next.(CopyInstruction).getSourceValue()
607-
or
608-
exists(ReadSideEffectInstruction read |
609-
next = read.getPrimaryInstruction() and
610-
isAdditionalConversionFlow(_, next) and
611-
prev = read.getSideEffectOperand().getAnyDef()
612-
)
613-
}
614-
615-
/**
616-
* Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
617-
* that is used for a write operation that writes the value `value`. The `memory` instruction
618-
* represents the memory that the IR's SSA analysis determined was read by the call to `operator*`.
619-
*
620-
* The `numberOfLoads` integer represents the number of dereferences this write corresponds to
621-
* on the underlying container that produced the iterator.
622-
*/
623-
private predicate isChiAfterIteratorDef(
624-
Instruction memory, Operand iteratorDerefAddress, Node0Impl value, int numberOfLoads
625-
) {
626-
exists(
627-
BaseSourceVariableInstruction iteratorBase, ReadSideEffectInstruction read,
628-
Operand iteratorAddress
629-
|
630-
numberOfLoads >= 0 and
631-
isDef(_, value, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
632-
isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
633-
iteratorBase.getResultType() instanceof Interfaces::Iterator and
634-
isDereference(iteratorAddress.getDef(), read.getArgumentDef().getAUse(), _) and
635-
memory = read.getSideEffectOperand().getAnyDef()
636-
)
637-
}
638-
639-
private predicate isSource(Instruction instr, Operand iteratorAddress, int numberOfLoads) {
640-
getAUse(instr) = iteratorAddress and
641-
exists(BaseSourceVariableInstruction iteratorBase |
642-
iteratorBase.getResultType() instanceof Interfaces::Iterator and
643-
not iteratorBase.getResultType() instanceof Cpp::PointerType and
644-
isUse(_, iteratorAddress, iteratorBase, numberOfLoads - 1, 0)
645-
)
646-
}
647-
648-
private predicate isSink(Instruction instr, CallInstruction call) {
649-
getAUse(instr).(ArgumentOperand).getCall() = call and
650-
// Only include operations that may modify the object that the iterator points to.
651-
// The following is a non-exhaustive list of things that may modify the value of the
652-
// iterator, but never the value of what the iterator points to.
653-
// The more things we can exclude here, the faster the small dataflow-like analysis
654-
// done by `convertsIntoArgument` will converge.
655-
not exists(Function f | f = call.getStaticCallTarget() |
656-
f instanceof Iterator::IteratorCrementOperator or
657-
f instanceof Iterator::IteratorBinaryArithmeticOperator or
658-
f instanceof Iterator::IteratorAssignArithmeticOperator or
659-
f instanceof Iterator::IteratorCrementMemberOperator or
660-
f instanceof Iterator::IteratorBinaryArithmeticMemberOperator or
661-
f instanceof Iterator::IteratorAssignArithmeticMemberOperator or
662-
f instanceof Iterator::IteratorAssignmentMemberOperator
663-
)
664-
}
665-
666-
private predicate convertsIntoArgumentFwd(Instruction instr) {
667-
isSource(instr, _, _)
668-
or
669-
exists(Instruction prev | convertsIntoArgumentFwd(prev) |
670-
conversionFlow(unique( | | getAUse(prev)), instr, false, _)
671-
)
672-
}
673-
674-
private predicate convertsIntoArgumentRev(Instruction instr) {
675-
convertsIntoArgumentFwd(instr) and
676-
(
677-
isSink(instr, _)
678-
or
679-
exists(Instruction next | convertsIntoArgumentRev(next) |
680-
conversionFlow(unique( | | getAUse(instr)), next, false, _)
681-
)
682-
)
683-
}
684-
685-
private predicate convertsIntoArgument(
686-
Operand iteratorAddress, CallInstruction call, int numberOfLoads
687-
) {
688-
exists(Instruction iteratorAddressDef |
689-
isSource(iteratorAddressDef, iteratorAddress, numberOfLoads) and
690-
isSink(iteratorAddressDef, call) and
691-
convertsIntoArgumentRev(pragma[only_bind_into](iteratorAddressDef))
692-
)
693-
}
694-
695-
private predicate isChiAfterIteratorArgument(
696-
Instruction memory, Operand iteratorAddress, int numberOfLoads
697-
) {
698-
// Ideally, `iteratorAddress` would be an `ArgumentOperand`, but there might be
699-
// various conversions applied to it before it becomes an argument.
700-
// So we do a small amount of flow to find the call that the iterator is passed to.
701-
exists(CallInstruction call | convertsIntoArgument(iteratorAddress, call, numberOfLoads) |
702-
exists(ReadSideEffectInstruction read |
703-
read.getPrimaryInstruction() = call and
704-
read.getSideEffectOperand().getAnyDef() = memory
705-
)
706-
or
707-
exists(LoadInstruction load |
708-
iteratorAddress.getDef() = load and
709-
memory = load.getSourceValueOperand().getAnyDef()
710-
)
711-
)
712-
}
713-
714-
/**
715-
* Holds if `iterator` is a `StoreInstruction` that stores the result of some function
716-
* returning an iterator into an address computed started at `containerBase`.
717-
*
718-
* For example, given a declaration like `std::vector<int>::iterator it = v.begin()`,
719-
* the `iterator` will be the `StoreInstruction` generated by the write to `it`, and
720-
* `containerBase` will be the address of `v`.
721-
*/
722-
private predicate isChiAfterBegin(
723-
BaseSourceVariableInstruction containerBase, StoreInstruction iterator
724-
) {
725-
exists(
726-
CallInstruction getIterator, Iterator::GetIteratorFunction getIteratorFunction,
727-
IO::FunctionInput input, int i
728-
|
729-
getIterator = iterator.getSourceValue() and
730-
getIteratorFunction = getIterator.getStaticCallTarget() and
731-
getIteratorFunction.getsIterator(input, _) and
732-
isDef(_, any(Node0Impl n | n.asInstruction() = iterator), _, _, 1, 0) and
733-
input.isParameterDerefOrQualifierObject(i) and
734-
isUse(_, getIterator.getArgumentOperand(i), containerBase, 0, 0)
735-
)
736-
}
737-
738-
/**
739-
* Holds if `iteratorAddress` is an address of an iterator that is used for
740-
* a read operation. The `memory` instruction represents the memory that
741-
* the IR's SSA analysis determined was read by the call to `operator*`.
742-
*
743-
* Finally, the `numberOfLoads` integer represents the number of dereferences
744-
* this read corresponds to on the underlying container that produced the iterator.
745-
*/
746-
private predicate isChiBeforeIteratorUse(
747-
Operand iteratorAddress, Instruction memory, int numberOfLoads
748-
) {
749-
exists(
750-
BaseSourceVariableInstruction iteratorBase, LoadInstruction load,
751-
ReadSideEffectInstruction read, Operand iteratorDerefAddress
752-
|
753-
numberOfLoads >= 0 and
754-
isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
755-
isUse(_, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
756-
iteratorBase.getResultType() instanceof Interfaces::Iterator and
757-
load.getSourceAddressOperand() = iteratorDerefAddress and
758-
read.getPrimaryInstruction() = load.getSourceAddress() and
759-
memory = read.getSideEffectOperand().getAnyDef()
760-
)
761-
}
762-
763-
/**
764-
* Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
765-
* that is used for a write operation that writes the value `value` to a container that
766-
* created the iterator. `container` represents the base of the address of the container
767-
* that was used to create the iterator.
768-
*/
769-
cached
770-
predicate isIteratorDef(
771-
BaseSourceVariableInstruction container, Operand iteratorDerefAddress, Node0Impl value,
772-
int numberOfLoads, int indirectionIndex
773-
) {
774-
exists(Instruction memory, Instruction begin, int upper, int ind |
775-
isChiAfterIteratorDef(memory, iteratorDerefAddress, value, numberOfLoads) and
776-
memorySucc*(begin, memory) and
777-
isChiAfterBegin(container, begin) and
778-
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
779-
ind = numberOfLoads + [1 .. upper] and
780-
indirectionIndex = ind - (numberOfLoads + 1)
781-
)
782-
}
783-
784-
/**
785-
* Holds if `iteratorAddress` is an address of an iterator that is used for a
786-
* read operation to read a value from a container that created the iterator.
787-
* `container` represents the base of the address of the container that was used
788-
* to create the iterator.
789-
*/
790-
cached
791-
predicate isIteratorUse(
792-
BaseSourceVariableInstruction container, Operand iteratorAddress, int numberOfLoads,
793-
int indirectionIndex
794-
) {
795-
// Direct use
796-
exists(Instruction begin, Instruction memory, int upper, int ind |
797-
isChiBeforeIteratorUse(iteratorAddress, memory, numberOfLoads) and
798-
memorySucc*(begin, memory) and
799-
isChiAfterBegin(container, begin) and
800-
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
801-
ind = numberOfLoads + [1 .. upper] and
802-
indirectionIndex = ind - (numberOfLoads + 1)
803-
)
804-
or
805-
// Use through function output
806-
exists(Instruction memory, Instruction begin, int upper, int ind |
807-
isChiAfterIteratorArgument(memory, iteratorAddress, numberOfLoads) and
808-
memorySucc*(begin, memory) and
809-
isChiAfterBegin(container, begin) and
810-
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
811-
ind = numberOfLoads + [1 .. upper] and
812-
indirectionIndex = ind - (numberOfLoads - 1)
813-
)
814-
}
815-
816574
/** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
817575
private predicate isConversion(Operand op) {
818576
exists(Instruction def, Operand use |

0 commit comments

Comments
 (0)