mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge pull request #12050 from MathiasVP/flow-out-of-iterators-3
This commit is contained in:
@@ -381,7 +381,7 @@ private Operand fullyConvertedCallStep(Operand op) {
|
||||
*/
|
||||
private Instruction getUse(Operand op) {
|
||||
result = op.getUse() and
|
||||
not Ssa::ignoreOperand(op)
|
||||
not Ssa::ignoreInstruction(result)
|
||||
}
|
||||
|
||||
/** Gets a use of the instruction `instr` that is not ignored for dataflow purposes. */
|
||||
|
||||
@@ -155,10 +155,10 @@ private newtype TDefOrUseImpl =
|
||||
)
|
||||
} or
|
||||
TIteratorDef(
|
||||
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
|
||||
Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex
|
||||
) {
|
||||
isIteratorDef(container, iteratorAddress, _, _, indirectionIndex) and
|
||||
any(SsaInternals0::Def def | def.isIteratorDef()).getAddressOperand() = iteratorAddress
|
||||
isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex) and
|
||||
any(SsaInternals0::Def def | def.isIteratorDef()).getAddressOperand() = iteratorDerefAddress
|
||||
} or
|
||||
TIteratorUse(
|
||||
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
|
||||
@@ -618,11 +618,20 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
|
||||
nodeToDefOrUse(nTo, defOrUse, _) and
|
||||
adjacentDefRead(defOrUse, _)
|
||||
) and
|
||||
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
|
||||
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
|
||||
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
|
||||
instr = op2.getDef() and
|
||||
conversionFlow(op1, instr, _, _)
|
||||
(
|
||||
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
|
||||
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
|
||||
hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and
|
||||
instr = op2.getDef() and
|
||||
conversionFlow(op1, instr, _, _)
|
||||
)
|
||||
or
|
||||
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
|
||||
hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and
|
||||
hasOperandAndIndex(nTo, op2, indirectionIndex - 1) and
|
||||
instr = op2.getDef() and
|
||||
isDereference(instr, op1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -408,7 +408,10 @@ private predicate isModifiableAtImpl(CppType cppType, int indirectionIndex) {
|
||||
(
|
||||
exists(Type pointerType, Type base, Type t |
|
||||
pointerType = t.getUnderlyingType() and
|
||||
(pointerType instanceof PointerOrReferenceType or pointerType instanceof Cpp::ArrayType) and
|
||||
(
|
||||
pointerType = any(Indirection ind).getUnderlyingType() or
|
||||
pointerType instanceof Cpp::ArrayType
|
||||
) and
|
||||
cppType.hasType(t, _) and
|
||||
base = getTypeImpl(pointerType, indirectionIndex)
|
||||
|
|
||||
@@ -504,6 +507,81 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isSource(Instruction instr, Operand iteratorAddress, int numberOfLoads) {
|
||||
getAUse(instr) = iteratorAddress and
|
||||
exists(BaseSourceVariableInstruction iteratorBase |
|
||||
iteratorBase.getResultType() instanceof Interfaces::Iterator and
|
||||
not iteratorBase.getResultType() instanceof Cpp::PointerType and
|
||||
isUse(_, iteratorAddress, iteratorBase, numberOfLoads - 1, 0)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isSink(Instruction instr, CallInstruction call) {
|
||||
getAUse(instr).(ArgumentOperand).getCall() = call and
|
||||
// Only include operations that may modify the object that the iterator points to.
|
||||
// The following is a non-exhaustive list of things that may modify the value of the
|
||||
// iterator, but never the value of what the iterator points to.
|
||||
// The more things we can exclude here, the faster the small dataflow-like analysis
|
||||
// done by `convertsIntoArgument` will converge.
|
||||
not exists(Function f | f = call.getStaticCallTarget() |
|
||||
f instanceof Iterator::IteratorCrementOperator or
|
||||
f instanceof Iterator::IteratorBinaryArithmeticOperator or
|
||||
f instanceof Iterator::IteratorAssignArithmeticOperator or
|
||||
f instanceof Iterator::IteratorCrementMemberOperator or
|
||||
f instanceof Iterator::IteratorBinaryArithmeticMemberOperator or
|
||||
f instanceof Iterator::IteratorAssignArithmeticMemberOperator or
|
||||
f instanceof Iterator::IteratorAssignmentMemberOperator
|
||||
)
|
||||
}
|
||||
|
||||
private predicate convertsIntoArgumentFwd(Instruction instr) {
|
||||
isSource(instr, _, _)
|
||||
or
|
||||
exists(Instruction prev | convertsIntoArgumentFwd(prev) |
|
||||
conversionFlow(unique( | | getAUse(prev)), instr, false, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate convertsIntoArgumentRev(Instruction instr) {
|
||||
convertsIntoArgumentFwd(instr) and
|
||||
(
|
||||
isSink(instr, _)
|
||||
or
|
||||
exists(Instruction next | convertsIntoArgumentRev(next) |
|
||||
conversionFlow(unique( | | getAUse(instr)), next, false, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate convertsIntoArgument(
|
||||
Operand iteratorAddress, CallInstruction call, int numberOfLoads
|
||||
) {
|
||||
exists(Instruction iteratorAddressDef |
|
||||
isSource(iteratorAddressDef, iteratorAddress, numberOfLoads) and
|
||||
isSink(iteratorAddressDef, call) and
|
||||
convertsIntoArgumentRev(pragma[only_bind_into](iteratorAddressDef))
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isChiAfterIteratorArgument(
|
||||
Instruction memory, Operand iteratorAddress, int numberOfLoads
|
||||
) {
|
||||
// Ideally, `iteratorAddress` would be an `ArgumentOperand`, but there might be
|
||||
// various conversions applied to it before it becomes an argument.
|
||||
// So we do a small amount of flow to find the call that the iterator is passed to.
|
||||
exists(CallInstruction call | convertsIntoArgument(iteratorAddress, call, numberOfLoads) |
|
||||
exists(ReadSideEffectInstruction read |
|
||||
read.getPrimaryInstruction() = call and
|
||||
read.getSideEffectOperand().getAnyDef() = memory
|
||||
)
|
||||
or
|
||||
exists(LoadInstruction load |
|
||||
iteratorAddress.getDef() = load and
|
||||
memory = load.getSourceValueOperand().getAnyDef()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `iterator` is a `StoreInstruction` that stores the result of some function
|
||||
* returning an iterator into an address computed started at `containerBase`.
|
||||
@@ -524,21 +602,22 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
|
||||
* that is used for a read operation. The `memory` instruction represents the memory that
|
||||
* Holds if `iteratorAddress` is an address of an iterator that is used for
|
||||
* a read operation. The `memory` instruction represents the memory that
|
||||
* the IR's SSA analysis determined was read by the call to `operator*`.
|
||||
*
|
||||
* Finally, the `numberOfLoads` integer represents the number of dereferences this read
|
||||
* corresponds to on the underlying container that produced the iterator.
|
||||
* Finally, the `numberOfLoads` integer represents the number of dereferences
|
||||
* this read corresponds to on the underlying container that produced the iterator.
|
||||
*/
|
||||
private predicate isChiBeforeIteratorUse(
|
||||
Operand iteratorDerefAddress, Instruction memory, int numberOfLoads
|
||||
Operand iteratorAddress, Instruction memory, int numberOfLoads
|
||||
) {
|
||||
exists(
|
||||
BaseSourceVariableInstruction iteratorBase, LoadInstruction load,
|
||||
ReadSideEffectInstruction read
|
||||
ReadSideEffectInstruction read, Operand iteratorDerefAddress
|
||||
|
|
||||
numberOfLoads >= 0 and
|
||||
isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
|
||||
isUse(_, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
|
||||
iteratorBase.getResultType() instanceof Interfaces::Iterator and
|
||||
load.getSourceAddressOperand() = iteratorDerefAddress and
|
||||
@@ -569,24 +648,35 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
|
||||
* that is used for a read operation to read a value from a container that created the iterator.
|
||||
* `container` represents the base of the address of the container that was used to create
|
||||
* the iterator.
|
||||
* Holds if `iteratorAddress` is an address of an iterator that is used for a
|
||||
* read operation to read a value from a container that created the iterator.
|
||||
* `container` represents the base of the address of the container that was used
|
||||
* to create the iterator.
|
||||
*/
|
||||
cached
|
||||
predicate isIteratorUse(
|
||||
BaseSourceVariableInstruction container, Operand iteratorDerefAddress, int numberOfLoads,
|
||||
BaseSourceVariableInstruction container, Operand iteratorAddress, int numberOfLoads,
|
||||
int indirectionIndex
|
||||
) {
|
||||
// Direct use
|
||||
exists(Instruction begin, Instruction memory, int upper, int ind |
|
||||
isChiBeforeIteratorUse(iteratorDerefAddress, memory, numberOfLoads) and
|
||||
isChiBeforeIteratorUse(iteratorAddress, memory, numberOfLoads) and
|
||||
memorySucc*(begin, memory) and
|
||||
isChiAfterBegin(container, begin) and
|
||||
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
|
||||
ind = numberOfLoads + [1 .. upper] and
|
||||
indirectionIndex = ind - (numberOfLoads + 1)
|
||||
)
|
||||
or
|
||||
// Use through function output
|
||||
exists(Instruction memory, Instruction begin, int upper, int ind |
|
||||
isChiAfterIteratorArgument(memory, iteratorAddress, numberOfLoads) and
|
||||
memorySucc*(begin, memory) and
|
||||
isChiAfterBegin(container, begin) and
|
||||
upper = countIndirectionsForCppType(getResultLanguageType(container)) and
|
||||
ind = numberOfLoads + [1 .. upper] and
|
||||
indirectionIndex = ind - (numberOfLoads - 1)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
|
||||
|
||||
@@ -3,10 +3,14 @@ edges
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode |
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode |
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode |
|
||||
| test.cpp:74:24:74:30 | medical | test.cpp:74:11:74:15 | buff1 |
|
||||
| test.cpp:74:24:74:30 | medical | test.cpp:78:11:78:15 | buff2 |
|
||||
| test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp |
|
||||
| test.cpp:74:24:74:30 | medical | test.cpp:81:22:81:28 | medical |
|
||||
| test.cpp:77:16:77:22 | medical | test.cpp:78:11:78:15 | buff2 |
|
||||
| test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp |
|
||||
| test.cpp:77:16:77:22 | medical | test.cpp:81:22:81:28 | medical |
|
||||
| test.cpp:81:17:81:20 | call to func | test.cpp:82:11:82:15 | buff3 |
|
||||
| test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 |
|
||||
| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer |
|
||||
| test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func |
|
||||
@@ -31,12 +35,15 @@ nodes
|
||||
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
|
||||
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
|
||||
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
|
||||
| test.cpp:74:11:74:15 | buff1 | semmle.label | buff1 |
|
||||
| test.cpp:74:24:74:30 | medical | semmle.label | medical |
|
||||
| test.cpp:74:24:74:30 | medical | semmle.label | medical |
|
||||
| test.cpp:77:16:77:22 | medical | semmle.label | medical |
|
||||
| test.cpp:78:11:78:15 | buff2 | semmle.label | buff2 |
|
||||
| test.cpp:78:24:78:27 | temp | semmle.label | temp |
|
||||
| test.cpp:81:17:81:20 | call to func | semmle.label | call to func |
|
||||
| test.cpp:81:22:81:28 | medical | semmle.label | medical |
|
||||
| test.cpp:82:11:82:15 | buff3 | semmle.label | buff3 |
|
||||
| test.cpp:82:24:82:28 | buff5 | semmle.label | buff5 |
|
||||
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
|
||||
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
|
||||
@@ -54,9 +61,15 @@ subpaths
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. |
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. |
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. |
|
||||
| test.cpp:74:11:74:15 | buff1 | test.cpp:74:24:74:30 | medical | test.cpp:74:11:74:15 | buff1 | This write into the external location 'buff1' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
|
||||
| test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
|
||||
| test.cpp:78:11:78:15 | buff2 | test.cpp:74:24:74:30 | medical | test.cpp:78:11:78:15 | buff2 | This write into the external location 'buff2' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
|
||||
| test.cpp:78:11:78:15 | buff2 | test.cpp:77:16:77:22 | medical | test.cpp:78:11:78:15 | buff2 | This write into the external location 'buff2' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. |
|
||||
| test.cpp:78:24:78:27 | temp | test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
|
||||
| test.cpp:78:24:78:27 | temp | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. |
|
||||
| test.cpp:82:11:82:15 | buff3 | test.cpp:74:24:74:30 | medical | test.cpp:82:11:82:15 | buff3 | This write into the external location 'buff3' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
|
||||
| test.cpp:82:11:82:15 | buff3 | test.cpp:77:16:77:22 | medical | test.cpp:82:11:82:15 | buff3 | This write into the external location 'buff3' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. |
|
||||
| test.cpp:82:11:82:15 | buff3 | test.cpp:81:22:81:28 | medical | test.cpp:82:11:82:15 | buff3 | This write into the external location 'buff3' may contain unencrypted data from $@. | test.cpp:81:22:81:28 | medical | this source of private data. |
|
||||
| test.cpp:82:24:82:28 | buff5 | test.cpp:74:24:74:30 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
|
||||
| test.cpp:82:24:82:28 | buff5 | test.cpp:77:16:77:22 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. |
|
||||
| test.cpp:82:24:82:28 | buff5 | test.cpp:81:22:81:28 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:81:22:81:28 | medical | this source of private data. |
|
||||
|
||||
@@ -8090,20 +8090,20 @@
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:523:8:523:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:524:8:524:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:526:8:526:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:539:8:539:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:540:2:540:2 | vs | |
|
||||
| vector.cpp:520:30:520:30 | 0 | vector.cpp:520:25:520:31 | call to vector | TAINT |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:524:8:524:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:526:8:526:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:539:8:539:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | |
|
||||
| vector.cpp:523:8:523:9 | vs | vector.cpp:523:10:523:10 | call to operator[] | TAINT |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:526:8:526:9 | vs | |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:539:8:539:9 | vs | |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | |
|
||||
| vector.cpp:524:8:524:9 | vs | vector.cpp:524:10:524:10 | call to operator[] | TAINT |
|
||||
| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:539:8:539:9 | vs | |
|
||||
| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | |
|
||||
| vector.cpp:526:8:526:9 | vs | vector.cpp:526:11:526:15 | call to begin | TAINT |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:526:3:526:17 | ... = ... | |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:527:9:527:10 | it | |
|
||||
@@ -8128,5 +8128,5 @@
|
||||
| vector.cpp:530:3:530:4 | ref arg it | vector.cpp:531:9:531:10 | it | |
|
||||
| vector.cpp:530:9:530:14 | call to source | vector.cpp:530:3:530:4 | ref arg it | TAINT |
|
||||
| vector.cpp:531:9:531:10 | it | vector.cpp:531:8:531:8 | call to operator* | TAINT |
|
||||
| vector.cpp:532:8:532:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:532:8:532:9 | vs | vector.cpp:532:10:532:10 | call to operator[] | TAINT |
|
||||
| vector.cpp:539:8:539:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | |
|
||||
| vector.cpp:539:8:539:9 | vs | vector.cpp:539:10:539:10 | call to operator[] | TAINT |
|
||||
|
||||
@@ -354,7 +354,7 @@ void test_vector_output_iterator(int b) {
|
||||
for(std::vector<int>::iterator it = v4.begin(); it != v4.end(); ++it) {
|
||||
taint_vector_output_iterator(it);
|
||||
}
|
||||
sink(v4); // $ ast MISSING: ir
|
||||
sink(v4); // $ ast,ir
|
||||
|
||||
std::vector<int>::iterator i5 = v5.begin();
|
||||
*i5 = source();
|
||||
@@ -389,7 +389,7 @@ void test_vector_output_iterator(int b) {
|
||||
*i9 = source();
|
||||
taint_vector_output_iterator(i9);
|
||||
|
||||
sink(v9); // $ ast=330:10 ir SPURIOUS: ast=389:8
|
||||
sink(v9); // $ ast=330:10 ir=330:10 SPURIOUS: ast=389:8 ir=389:8
|
||||
|
||||
std::vector<int>::iterator i10 = v10.begin();
|
||||
vector_iterator_assign_wrapper(i10, 10);
|
||||
@@ -397,7 +397,7 @@ void test_vector_output_iterator(int b) {
|
||||
|
||||
std::vector<int>::iterator i11 = v11.begin();
|
||||
vector_iterator_assign_wrapper(i11, source());
|
||||
sink(v11); // $ ast MISSING: ir
|
||||
sink(v11); // $ ast,ir
|
||||
|
||||
std::vector<int>::iterator i12 = v12.begin();
|
||||
*i12++ = 0;
|
||||
@@ -523,12 +523,19 @@ void test_vector_iterator() {
|
||||
sink(vs[1]);
|
||||
sink(vs[source()]); // $ MISSING: ast,ir
|
||||
|
||||
it = vs.begin();
|
||||
it = vs.begin(); // (1)
|
||||
sink(*it);
|
||||
it += 1;
|
||||
sink(*it);
|
||||
it += source();
|
||||
sink(*it); // $ ast,ir
|
||||
sink(vs[1]);
|
||||
it += source(); // (2)
|
||||
sink(*it); // $ ast,ir // (3)
|
||||
// This FP happens because of the following flows:
|
||||
// 1. There's a write to the iterator at (2)
|
||||
// 2. This write propagates to `it` on the next line at (3)
|
||||
// 3. There's a taint step from `it` to `*it` at (3)
|
||||
// 4. The `*it` is seen as a use of `vs` because of (1).
|
||||
// 5. There's use-use flow from `*it` at (3) (which is a use of `vs`) to `vs` at (4)
|
||||
// 6. There's a taint step from vs to vs[1]
|
||||
sink(vs[1]); // $ SPURIOUS: ir // (4)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,42 @@
|
||||
edges
|
||||
| tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
|
||||
| tests.cpp:26:32:26:35 | data | tests.cpp:26:15:26:23 | badSource indirection |
|
||||
| tests.cpp:26:32:26:35 | data | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection |
|
||||
| tests.cpp:26:32:26:35 | data indirection | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:38:39:38:49 | (const char *)... indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:51:22:51:25 | badSource output argument |
|
||||
| tests.cpp:38:39:38:49 | (const char *)... indirection | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:51:12:51:20 | call to badSource indirection | tests.cpp:53:16:53:19 | (const char *)... indirection |
|
||||
| tests.cpp:51:22:51:25 | badSource output argument | tests.cpp:51:22:51:25 | data |
|
||||
| tests.cpp:51:22:51:25 | badSource output argument | tests.cpp:51:22:51:25 | data indirection |
|
||||
| tests.cpp:51:22:51:25 | data | tests.cpp:26:32:26:35 | data |
|
||||
| tests.cpp:51:22:51:25 | data | tests.cpp:51:12:51:20 | call to badSource indirection |
|
||||
| tests.cpp:51:22:51:25 | data | tests.cpp:51:22:51:25 | badSource output argument |
|
||||
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection |
|
||||
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
|
||||
nodes
|
||||
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
|
||||
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
|
||||
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
|
||||
| tests.cpp:26:32:26:35 | data | semmle.label | data |
|
||||
| tests.cpp:26:32:26:35 | data indirection | semmle.label | data indirection |
|
||||
| tests.cpp:33:34:33:39 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
|
||||
| tests.cpp:38:39:38:49 | (const char *)... indirection | semmle.label | (const char *)... indirection |
|
||||
| tests.cpp:51:12:51:20 | call to badSource indirection | semmle.label | call to badSource indirection |
|
||||
| tests.cpp:51:22:51:25 | badSource output argument | semmle.label | badSource output argument |
|
||||
| tests.cpp:51:22:51:25 | data | semmle.label | data |
|
||||
| tests.cpp:51:22:51:25 | data indirection | semmle.label | data indirection |
|
||||
| tests.cpp:53:16:53:19 | (const char *)... indirection | semmle.label | (const char *)... indirection |
|
||||
subpaths
|
||||
| tests.cpp:51:22:51:25 | data | tests.cpp:26:32:26:35 | data | tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
|
||||
| tests.cpp:51:22:51:25 | data | tests.cpp:26:32:26:35 | data | tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:51:22:51:25 | badSource output argument |
|
||||
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
|
||||
#select
|
||||
| tests.cpp:53:16:53:19 | data | tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:53:16:53:19 | (const char *)... indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | tests.cpp:33:34:33:39 | call to getenv indirection | user input (an environment variable) | tests.cpp:38:25:38:36 | strncat output argument | strncat output argument |
|
||||
|
||||
@@ -46,6 +46,9 @@ edges
|
||||
| test.cpp:186:47:186:54 | filename indirection | test.cpp:188:20:188:24 | (const char *)... indirection |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
|
||||
| test.cpp:187:18:187:25 | (const char *)... indirection | test.cpp:187:11:187:15 | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
|
||||
| test.cpp:188:20:188:24 | (const char *)... indirection | test.cpp:188:11:188:17 | strncat output argument |
|
||||
| test.cpp:188:20:188:24 | (const char *)... indirection | test.cpp:188:11:188:17 | strncat output argument |
|
||||
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | array to pointer conversion indirection |
|
||||
|
||||
@@ -17,6 +17,7 @@ edges
|
||||
| overflowdestination.cpp:50:52:50:54 | src | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
|
||||
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src |
|
||||
| overflowdestination.cpp:53:9:53:12 | memcpy output argument | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
|
||||
| overflowdestination.cpp:54:9:54:12 | memcpy output argument | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
|
||||
| overflowdestination.cpp:57:52:57:54 | src | overflowdestination.cpp:64:16:64:19 | src2 |
|
||||
| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 |
|
||||
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | array to pointer conversion indirection |
|
||||
|
||||
Reference in New Issue
Block a user