Merge pull request #12050 from MathiasVP/flow-out-of-iterators-3

This commit is contained in:
Mathias Vorreiter Pedersen
2023-02-03 18:43:37 +00:00
committed by GitHub
9 changed files with 188 additions and 39 deletions

View File

@@ -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. */

View File

@@ -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)
)
)
}

View File

@@ -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 */

View File

@@ -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. |

View File

@@ -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 |

View File

@@ -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)
}
}

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |