mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Merge branch 'main' into log-injection-mad
This commit is contained in:
@@ -171,11 +171,9 @@ private predicate invalidPointerToDerefSource(
|
||||
// `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction
|
||||
// and the instruction computing the address for which we will search for a dereference.
|
||||
AllocToInvalidPointer::pointerAddInstructionHasBounds(allocSource, pai, _, rhsSizeDelta) and
|
||||
// pai <= derefSource + deltaDerefSourceAndPai and deltaDerefSourceAndPai <= 0 is equivalent to
|
||||
// derefSource >= pai + deltaDerefSourceAndPai and deltaDerefSourceAndPai >= 0
|
||||
bounded1(pai, derefSource.asInstruction(), deltaDerefSourceAndPai) and
|
||||
deltaDerefSourceAndPai <= 0 and
|
||||
// TODO: This condition will go away once #13725 is merged, and then we can make `Barrier2`
|
||||
bounded2(derefSource.asInstruction(), pai, deltaDerefSourceAndPai) and
|
||||
deltaDerefSourceAndPai >= 0 and
|
||||
// TODO: This condition will go away once #13725 is merged, and then we can make `SizeBarrier`
|
||||
// private to `AllocationToInvalidPointer.qll`.
|
||||
not derefSource.getBasicBlock() =
|
||||
AllocToInvalidPointer::SizeBarrier::getABarrierBlock(rhsSizeDelta)
|
||||
|
||||
@@ -35,5 +35,14 @@ bindingset[i]
|
||||
pragma[inline_late]
|
||||
predicate bounded1(Instruction i, Instruction b, int delta) { boundedImpl(i, b, delta) }
|
||||
|
||||
/**
|
||||
* Holds if `i <= b + delta`.
|
||||
*
|
||||
* This predicate enforces a join-order that ensures that `b` has already been bound.
|
||||
*/
|
||||
bindingset[b]
|
||||
pragma[inline_late]
|
||||
predicate bounded2(Instruction i, Instruction b, int delta) { boundedImpl(i, b, delta) }
|
||||
|
||||
/** Holds if `i <= b + delta`. */
|
||||
predicate bounded = boundedImpl/3;
|
||||
|
||||
@@ -132,6 +132,8 @@ edges
|
||||
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | ... = ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:357:24:357:30 | ... + ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:357:24:357:30 | ... + ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | * ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | * ... |
|
||||
| test.cpp:356:15:356:23 | ... + ... | test.cpp:356:15:356:23 | ... + ... |
|
||||
@@ -139,46 +141,93 @@ edges
|
||||
| test.cpp:356:15:356:23 | ... + ... | test.cpp:358:14:358:26 | * ... |
|
||||
| test.cpp:356:15:356:23 | ... + ... | test.cpp:359:14:359:32 | * ... |
|
||||
| test.cpp:356:15:356:23 | ... + ... | test.cpp:359:14:359:32 | * ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | test.cpp:357:24:357:30 | ... + ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | test.cpp:358:14:358:26 | * ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | test.cpp:358:14:358:26 | * ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | test.cpp:359:14:359:32 | * ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | test.cpp:359:14:359:32 | * ... |
|
||||
| test.cpp:377:14:377:27 | new[] | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:377:14:377:27 | new[] | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:377:14:377:27 | new[] | test.cpp:381:5:381:9 | ... ++ |
|
||||
| test.cpp:377:14:377:27 | new[] | test.cpp:381:5:381:9 | ... ++ |
|
||||
| test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | * ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:13:384:16 | * ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:13:384:16 | * ... |
|
||||
| test.cpp:381:5:381:9 | ... ++ | test.cpp:381:5:381:9 | ... ++ |
|
||||
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:13:384:16 | * ... |
|
||||
| test.cpp:410:14:410:27 | new[] | test.cpp:411:15:411:23 | & ... |
|
||||
| test.cpp:410:14:410:27 | new[] | test.cpp:411:15:411:23 | & ... |
|
||||
| test.cpp:410:14:410:27 | new[] | test.cpp:413:5:413:8 | ... ++ |
|
||||
| test.cpp:410:14:410:27 | new[] | test.cpp:413:5:413:8 | ... ++ |
|
||||
| test.cpp:410:14:410:27 | new[] | test.cpp:415:7:415:15 | ... = ... |
|
||||
| test.cpp:411:15:411:23 | & ... | test.cpp:411:15:411:23 | & ... |
|
||||
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | ... = ... |
|
||||
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | ... = ... |
|
||||
| test.cpp:413:5:413:8 | ... ++ | test.cpp:413:5:413:8 | ... ++ |
|
||||
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | ... = ... |
|
||||
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | ... = ... |
|
||||
| test.cpp:421:14:421:27 | new[] | test.cpp:422:15:422:23 | & ... |
|
||||
| test.cpp:421:14:421:27 | new[] | test.cpp:422:15:422:23 | & ... |
|
||||
| test.cpp:421:14:421:27 | new[] | test.cpp:424:5:424:8 | ... ++ |
|
||||
| test.cpp:421:14:421:27 | new[] | test.cpp:424:5:424:8 | ... ++ |
|
||||
| test.cpp:421:14:421:27 | new[] | test.cpp:426:7:426:15 | ... = ... |
|
||||
| test.cpp:422:15:422:23 | & ... | test.cpp:422:15:422:23 | & ... |
|
||||
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | ... = ... |
|
||||
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | ... = ... |
|
||||
| test.cpp:424:5:424:8 | ... ++ | test.cpp:424:5:424:8 | ... ++ |
|
||||
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | ... = ... |
|
||||
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | ... = ... |
|
||||
| test.cpp:432:14:432:27 | new[] | test.cpp:433:15:433:23 | & ... |
|
||||
| test.cpp:432:14:432:27 | new[] | test.cpp:433:15:433:23 | & ... |
|
||||
| test.cpp:432:14:432:27 | new[] | test.cpp:436:5:436:8 | ... ++ |
|
||||
| test.cpp:432:14:432:27 | new[] | test.cpp:436:5:436:8 | ... ++ |
|
||||
| test.cpp:432:14:432:27 | new[] | test.cpp:438:7:438:15 | ... = ... |
|
||||
| test.cpp:433:15:433:23 | & ... | test.cpp:433:15:433:23 | & ... |
|
||||
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | ... = ... |
|
||||
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | ... = ... |
|
||||
| test.cpp:436:5:436:8 | ... ++ | test.cpp:436:5:436:8 | ... ++ |
|
||||
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | ... = ... |
|
||||
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | ... = ... |
|
||||
| test.cpp:444:14:444:27 | new[] | test.cpp:445:15:445:23 | & ... |
|
||||
| test.cpp:444:14:444:27 | new[] | test.cpp:445:15:445:23 | & ... |
|
||||
| test.cpp:444:14:444:27 | new[] | test.cpp:448:5:448:8 | ... ++ |
|
||||
| test.cpp:444:14:444:27 | new[] | test.cpp:448:5:448:8 | ... ++ |
|
||||
| test.cpp:444:14:444:27 | new[] | test.cpp:450:7:450:15 | ... = ... |
|
||||
| test.cpp:445:15:445:23 | & ... | test.cpp:445:15:445:23 | & ... |
|
||||
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | ... = ... |
|
||||
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | ... = ... |
|
||||
| test.cpp:448:5:448:8 | ... ++ | test.cpp:448:5:448:8 | ... ++ |
|
||||
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | ... = ... |
|
||||
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | ... = ... |
|
||||
| test.cpp:480:14:480:27 | new[] | test.cpp:481:15:481:23 | & ... |
|
||||
| test.cpp:480:14:480:27 | new[] | test.cpp:481:15:481:23 | & ... |
|
||||
| test.cpp:480:14:480:27 | new[] | test.cpp:484:5:484:8 | ... ++ |
|
||||
| test.cpp:480:14:480:27 | new[] | test.cpp:484:5:484:8 | ... ++ |
|
||||
| test.cpp:480:14:480:27 | new[] | test.cpp:486:7:486:15 | ... = ... |
|
||||
| test.cpp:481:15:481:23 | & ... | test.cpp:481:15:481:23 | & ... |
|
||||
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | ... = ... |
|
||||
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | ... = ... |
|
||||
| test.cpp:484:5:484:8 | ... ++ | test.cpp:484:5:484:8 | ... ++ |
|
||||
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | ... = ... |
|
||||
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | ... = ... |
|
||||
| test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... |
|
||||
| test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... |
|
||||
| test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... |
|
||||
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:6 | ... ++ |
|
||||
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:6 | ... ++ |
|
||||
| test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | ... = ... |
|
||||
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
|
||||
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | ... = ... |
|
||||
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | ... = ... |
|
||||
| test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | ... = ... |
|
||||
| test.cpp:695:13:695:26 | new[] | test.cpp:698:5:698:10 | ... += ... |
|
||||
| test.cpp:698:5:698:10 | ... += ... | test.cpp:701:15:701:16 | * ... |
|
||||
| test.cpp:705:18:705:18 | q | test.cpp:705:18:705:18 | q |
|
||||
| test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... |
|
||||
| test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... |
|
||||
| test.cpp:711:13:711:26 | new[] | test.cpp:714:11:714:11 | q |
|
||||
| test.cpp:714:11:714:11 | q | test.cpp:705:18:705:18 | q |
|
||||
nodes
|
||||
| test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... |
|
||||
@@ -276,31 +325,45 @@ nodes
|
||||
| test.cpp:355:14:355:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:357:24:357:30 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:358:14:358:26 | * ... | semmle.label | * ... |
|
||||
| test.cpp:359:14:359:32 | * ... | semmle.label | * ... |
|
||||
| test.cpp:377:14:377:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:381:5:381:9 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:381:5:381:9 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:384:13:384:16 | * ... | semmle.label | * ... |
|
||||
| test.cpp:410:14:410:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:415:7:415:15 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:421:14:421:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:426:7:426:15 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:432:14:432:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:438:7:438:15 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:444:14:444:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:450:7:450:15 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:480:14:480:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
|
||||
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:486:7:486:15 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:543:14:543:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:548:5:548:19 | ... = ... | semmle.label | ... = ... |
|
||||
@@ -308,8 +371,20 @@ nodes
|
||||
| test.cpp:559:5:559:19 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:642:14:642:31 | new[] | semmle.label | new[] |
|
||||
| test.cpp:647:5:647:19 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:652:14:652:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:662:3:662:11 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:667:14:667:31 | new[] | semmle.label | new[] |
|
||||
| test.cpp:675:7:675:23 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:695:13:695:26 | new[] | semmle.label | new[] |
|
||||
| test.cpp:698:5:698:10 | ... += ... | semmle.label | ... += ... |
|
||||
| test.cpp:701:15:701:16 | * ... | semmle.label | * ... |
|
||||
| test.cpp:705:18:705:18 | q | semmle.label | q |
|
||||
| test.cpp:705:18:705:18 | q | semmle.label | q |
|
||||
| test.cpp:706:12:706:13 | * ... | semmle.label | * ... |
|
||||
| test.cpp:711:13:711:26 | new[] | semmle.label | new[] |
|
||||
| test.cpp:714:11:714:11 | q | semmle.label | q |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
|
||||
@@ -343,4 +418,7 @@ subpaths
|
||||
| test.cpp:548:5:548:19 | ... = ... | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:543:14:543:27 | new[] | new[] | test.cpp:548:8:548:14 | src_pos | src_pos |
|
||||
| test.cpp:559:5:559:19 | ... = ... | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:554:14:554:27 | new[] | new[] | test.cpp:559:8:559:14 | src_pos | src_pos |
|
||||
| test.cpp:647:5:647:19 | ... = ... | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:642:14:642:31 | new[] | new[] | test.cpp:647:8:647:14 | src_pos | src_pos |
|
||||
| test.cpp:662:3:662:11 | ... = ... | test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:652:14:652:27 | new[] | new[] | test.cpp:653:19:653:22 | size | size |
|
||||
| test.cpp:675:7:675:23 | ... = ... | test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:667:14:667:31 | new[] | new[] | test.cpp:675:10:675:18 | ... ++ | ... ++ |
|
||||
| test.cpp:701:15:701:16 | * ... | test.cpp:695:13:695:26 | new[] | test.cpp:701:15:701:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:695:13:695:26 | new[] | new[] | test.cpp:696:19:696:22 | size | size |
|
||||
| test.cpp:706:12:706:13 | * ... | test.cpp:711:13:711:26 | new[] | test.cpp:706:12:706:13 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:711:13:711:26 | new[] | new[] | test.cpp:712:19:712:22 | size | size |
|
||||
|
||||
@@ -17,7 +17,7 @@ void test2(int size) {
|
||||
char* q = p + size - 1; // $ alloc=L16
|
||||
char a = *q; // GOOD
|
||||
char b = *(q - 1); // GOOD
|
||||
char c = *(q + 1); // $ deref=L17->L20 // BAD
|
||||
char c = *(q + 1); // $ deref=L20 // BAD
|
||||
char d = *(q + size); // BAD [NOT DETECTED]
|
||||
char e = *(q - size); // GOOD
|
||||
char f = *(q + size + 1); // BAD [NOT DETECTED]
|
||||
@@ -198,7 +198,7 @@ void test12(unsigned len, unsigned index) {
|
||||
return;
|
||||
}
|
||||
|
||||
p[index] = '\0'; // $ deref=L195->L201 deref=L197->L201 // BAD
|
||||
p[index] = '\0'; // $ deref=L201 // BAD
|
||||
}
|
||||
|
||||
void test13(unsigned len, unsigned index) {
|
||||
@@ -210,7 +210,7 @@ void test13(unsigned len, unsigned index) {
|
||||
return;
|
||||
}
|
||||
|
||||
*q = '\0'; // $ deref=L206->L213 deref=L209->L213 // BAD
|
||||
*q = '\0'; // $ deref=L213 // BAD
|
||||
}
|
||||
|
||||
bool unknown();
|
||||
@@ -261,7 +261,7 @@ void test17(unsigned len)
|
||||
int *end = xs + len; // $ alloc=L260
|
||||
for (int *x = xs; x <= end; x++)
|
||||
{
|
||||
int i = *x; // $ deref=L261->L264 deref=L262->L264 // BAD
|
||||
int i = *x; // $ deref=L264 // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ void test18(unsigned len)
|
||||
int *end = xs + len; // $ alloc=L270
|
||||
for (int *x = xs; x <= end; x++)
|
||||
{
|
||||
*x = 0; // $ deref=L271->L274 deref=L272->L274 // BAD
|
||||
*x = 0; // $ deref=L274 // BAD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,8 +355,8 @@ void test25(unsigned size) {
|
||||
char *xs = new char[size];
|
||||
char *end = xs + size; // $ alloc=L355
|
||||
char *end_plus_one = end + 1;
|
||||
int val1 = *end_plus_one; // $ deref=L356->L358+1 deref=L357->L358+1 // BAD
|
||||
int val2 = *(end_plus_one + 1); // $ deref=L356->L359+2 deref=L357->L359+2 // BAD
|
||||
int val1 = *end_plus_one; // $ deref=L358+1 // BAD
|
||||
int val2 = *(end_plus_one + 1); // $ deref=L359+2 // BAD
|
||||
}
|
||||
|
||||
void test26(unsigned size) {
|
||||
@@ -381,7 +381,7 @@ void test27(unsigned size, bool b) {
|
||||
end++;
|
||||
}
|
||||
|
||||
int val = *end; // $ deref=L378->L384+1 deref=L381->L384+1 // BAD
|
||||
int val = *end; // $ deref=L384+1 // BAD
|
||||
}
|
||||
|
||||
void test28(unsigned size) {
|
||||
@@ -412,7 +412,7 @@ void test28_simple2(unsigned size) {
|
||||
if (xs < end) {
|
||||
xs++;
|
||||
if (xs < end + 1) {
|
||||
xs[0] = 0; // $ deref=L411->L415 deref=L412->L415 deref=L414->L415 // BAD
|
||||
xs[0] = 0; // $ deref=L415 // BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,7 +423,7 @@ void test28_simple3(unsigned size) {
|
||||
if (xs < end) {
|
||||
xs++;
|
||||
if (xs - 1 < end) {
|
||||
xs[0] = 0; // $ deref=L422->L426 deref=L423->L426 deref=L425->L426 // BAD
|
||||
xs[0] = 0; // $ deref=L426 // BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,7 +435,7 @@ void test28_simple4(unsigned size) {
|
||||
end++;
|
||||
xs++;
|
||||
if (xs < end) {
|
||||
xs[0] = 0; // $ deref=L433->L438 deref=L434->L438 deref=L435->L438 // BAD
|
||||
xs[0] = 0; // $ deref=L438 // BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,7 +447,7 @@ void test28_simple5(unsigned size) {
|
||||
if (xs < end) {
|
||||
xs++;
|
||||
if (xs < end) {
|
||||
xs[0] = 0; // $ deref=L445->L450 deref=L446->L450 // BAD
|
||||
xs[0] = 0; // $ deref=L450 // BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -483,7 +483,7 @@ void test28_simple8(unsigned size) {
|
||||
if (xs < end) {
|
||||
xs++;
|
||||
if (xs < end - 1) {
|
||||
xs[0] = 0; // $ deref=L481->L486+498 deref=L482->L486+498 // BAD
|
||||
xs[0] = 0; // $ deref=L486+498 // BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -659,7 +659,7 @@ void test32(unsigned size) {
|
||||
xs++;
|
||||
if (xs >= end)
|
||||
return;
|
||||
xs[0] = 0; // $ GOOD
|
||||
xs[0] = 0; // $ deref=L656->L662+1 deref=L657->L662+1 GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test33(unsigned size, unsigned src_pos)
|
||||
@@ -698,12 +698,12 @@ void test34(unsigned size) {
|
||||
p += 1;
|
||||
}
|
||||
if (p + 1 < end) {
|
||||
int val = *p; // GOOD
|
||||
int val = *p; // $ deref=L698->L700->L701 // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void deref(char* q) {
|
||||
char x = *q; // $ MISSING: deref=L712->L706 deref=L713->L706
|
||||
char x = *q; // $ deref=L714->L705->L706 // BAD
|
||||
}
|
||||
|
||||
void test35(unsigned long size, char* q)
|
||||
|
||||
@@ -15030,25 +15030,28 @@ ir.cpp:
|
||||
# 1999| Value = [Literal] 5
|
||||
# 1999| ValueCategory = prvalue
|
||||
# 2000| getStmt(3): [ExprStmt] ExprStmt
|
||||
# 2000| getExpr(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2000| getExpr(): [AssignExpr] ... = ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getCondition(): [VariableAccess] a
|
||||
# 2000| Type = [BoolType] bool
|
||||
# 2000| ValueCategory = prvalue(load)
|
||||
# 2000| getThen(): [VariableAccess] x
|
||||
# 2000| getLValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getElse(): [AssignExpr] ... = ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getLValue(): [VariableAccess] y
|
||||
# 2000| getCondition(): [VariableAccess] a
|
||||
# 2000| Type = [BoolType] bool
|
||||
# 2000| ValueCategory = prvalue(load)
|
||||
# 2000| getThen(): [VariableAccess] x
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getRValue(): [Literal] 7
|
||||
# 2000| getElse(): [VariableAccess] y
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| Value = [Literal] 7
|
||||
# 2000| ValueCategory = prvalue
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getRValue(): [Literal] 7
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| Value = [Literal] 7
|
||||
# 2000| ValueCategory = prvalue
|
||||
# 2000| getLValue().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2001| getStmt(4): [ReturnStmt] return ...
|
||||
# 2003| [CopyAssignmentOperator] TernaryPodObj& TernaryPodObj::operator=(TernaryPodObj const&)
|
||||
# 2003| <params>:
|
||||
@@ -15151,31 +15154,34 @@ ir.cpp:
|
||||
# 2010| getExpr(): [AssignExpr] ... = ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getLValue(): [VariableAccess] z
|
||||
# 2010| getLValue(): [AssignExpr] ... = ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getCondition(): [VariableAccess] a
|
||||
# 2010| Type = [BoolType] bool
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getThen(): [VariableAccess] x
|
||||
# 2010| getLValue(): [VariableAccess] z
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getElse(): [AssignExpr] ... = ...
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getLValue(): [VariableAccess] y
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [Literal] 0
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| Value = [Literal] 0
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2010| getCondition(): [VariableAccess] a
|
||||
# 2010| Type = [BoolType] bool
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getThen(): [VariableAccess] x
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getElse(): [VariableAccess] y
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getRValue(): [Literal] 0
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| Value = [Literal] 0
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getLValue().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2011| getStmt(4): [ReturnStmt] return ...
|
||||
# 2013| [CopyAssignmentOperator] TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&)
|
||||
# 2013| <params>:
|
||||
@@ -15339,38 +15345,38 @@ ir.cpp:
|
||||
# 2021| getExpr(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] z
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getCondition(): [VariableAccess] a
|
||||
# 2021| Type = [BoolType] bool
|
||||
# 2021| ValueCategory = prvalue(load)
|
||||
# 2021| getThen(): [VariableAccess] x
|
||||
# 2021| getQualifier(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] z
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getElse(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] y
|
||||
# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getCondition(): [VariableAccess] a
|
||||
# 2021| Type = [BoolType] bool
|
||||
# 2021| ValueCategory = prvalue(load)
|
||||
# 2021| getThen(): [VariableAccess] x
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2021| Type = [VoidType] void
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2021| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getElse().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| getElse(): [VariableAccess] y
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2021| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2021| Type = [VoidType] void
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
@@ -15380,6 +15386,9 @@ ir.cpp:
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
|
||||
@@ -1997,7 +1997,7 @@ void TernaryTestInt(bool a, int x, int y, int z) {
|
||||
z = a ? x : y;
|
||||
z = a ? x : 5;
|
||||
z = a ? 3 : 5;
|
||||
a ? x : y = 7;
|
||||
(a ? x : y) = 7;
|
||||
}
|
||||
|
||||
struct TernaryPodObj {
|
||||
@@ -2007,7 +2007,7 @@ void TernaryTestPodObj(bool a, TernaryPodObj x, TernaryPodObj y, TernaryPodObj z
|
||||
z = a ? x : y;
|
||||
z = a ? x : TernaryPodObj();
|
||||
z = a ? TernaryPodObj() : TernaryPodObj();
|
||||
z = a ? x : y = TernaryPodObj();
|
||||
(z = a ? x : y) = TernaryPodObj();
|
||||
}
|
||||
|
||||
struct TernaryNonPodObj {
|
||||
@@ -2018,7 +2018,7 @@ void TernaryTestNonPodObj(bool a, TernaryNonPodObj x, TernaryNonPodObj y, Ternar
|
||||
z = a ? x : y;
|
||||
z = a ? x : TernaryNonPodObj();
|
||||
z = a ? TernaryNonPodObj() : TernaryNonPodObj();
|
||||
z = a ? x : y = TernaryNonPodObj();
|
||||
(z = a ? x : y) = TernaryNonPodObj();
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -9078,7 +9078,7 @@
|
||||
| ir.cpp:1993:13:1993:32 | StoreValue | r1993_2 |
|
||||
| ir.cpp:1996:6:1996:19 | ChiPartial | partial:m1996_3 |
|
||||
| ir.cpp:1996:6:1996:19 | ChiTotal | total:m1996_2 |
|
||||
| ir.cpp:1996:6:1996:19 | SideEffect | m1996_3 |
|
||||
| ir.cpp:1996:6:1996:19 | SideEffect | ~m2000_9 |
|
||||
| ir.cpp:1996:26:1996:26 | Address | &:r1996_5 |
|
||||
| ir.cpp:1996:33:1996:33 | Address | &:r1996_7 |
|
||||
| ir.cpp:1996:40:1996:40 | Address | &:r1996_9 |
|
||||
@@ -9128,20 +9128,21 @@
|
||||
| ir.cpp:1999:9:1999:17 | StoreValue | r1999_6 |
|
||||
| ir.cpp:1999:13:1999:13 | StoreValue | r1999_9 |
|
||||
| ir.cpp:1999:17:1999:17 | StoreValue | r1999_12 |
|
||||
| ir.cpp:2000:5:2000:5 | Address | &:r2000_1 |
|
||||
| ir.cpp:2000:5:2000:5 | Condition | r2000_2 |
|
||||
| ir.cpp:2000:5:2000:5 | Load | m1996_6 |
|
||||
| ir.cpp:2000:5:2000:17 | Address | &:r2000_5 |
|
||||
| ir.cpp:2000:5:2000:17 | Address | &:r2000_8 |
|
||||
| ir.cpp:2000:5:2000:17 | Address | &:r2000_14 |
|
||||
| ir.cpp:2000:5:2000:17 | Load | m2000_4 |
|
||||
| ir.cpp:2000:5:2000:17 | Phi | from 11:m2000_9 |
|
||||
| ir.cpp:2000:5:2000:17 | Phi | from 12:m2000_15 |
|
||||
| ir.cpp:2000:9:2000:9 | StoreValue | r2000_7 |
|
||||
| ir.cpp:2000:13:2000:13 | Address | &:r2000_11 |
|
||||
| ir.cpp:2000:13:2000:13 | Unary | r2000_11 |
|
||||
| ir.cpp:2000:13:2000:17 | StoreValue | r2000_13 |
|
||||
| ir.cpp:2000:17:2000:17 | StoreValue | r2000_10 |
|
||||
| ir.cpp:2000:5:2000:19 | ChiPartial | partial:m2000_8 |
|
||||
| ir.cpp:2000:5:2000:19 | ChiTotal | total:m1996_4 |
|
||||
| ir.cpp:2000:6:2000:6 | Address | &:r2000_2 |
|
||||
| ir.cpp:2000:6:2000:6 | Condition | r2000_3 |
|
||||
| ir.cpp:2000:6:2000:6 | Load | m1996_6 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_6 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_7 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_11 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_14 |
|
||||
| ir.cpp:2000:6:2000:14 | Load | m2000_5 |
|
||||
| ir.cpp:2000:6:2000:14 | Phi | from 11:m2000_12 |
|
||||
| ir.cpp:2000:6:2000:14 | Phi | from 12:m2000_15 |
|
||||
| ir.cpp:2000:10:2000:10 | StoreValue | r2000_10 |
|
||||
| ir.cpp:2000:14:2000:14 | StoreValue | r2000_13 |
|
||||
| ir.cpp:2000:19:2000:19 | StoreValue | r2000_1 |
|
||||
| ir.cpp:2006:6:2006:22 | ChiPartial | partial:m2006_3 |
|
||||
| ir.cpp:2006:6:2006:22 | ChiTotal | total:m2006_2 |
|
||||
| ir.cpp:2006:6:2006:22 | SideEffect | m2006_3 |
|
||||
@@ -9218,28 +9219,30 @@
|
||||
| ir.cpp:2009:31:2009:45 | Load | m2009_20 |
|
||||
| ir.cpp:2009:31:2009:45 | StoreValue | r2009_19 |
|
||||
| ir.cpp:2009:31:2009:45 | StoreValue | r2009_21 |
|
||||
| ir.cpp:2010:5:2010:5 | Address | &:r2010_7 |
|
||||
| ir.cpp:2010:9:2010:9 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:9:2010:9 | Condition | r2010_2 |
|
||||
| ir.cpp:2010:9:2010:9 | Load | m2006_6 |
|
||||
| ir.cpp:2010:9:2010:35 | Address | &:r2010_5 |
|
||||
| ir.cpp:2010:9:2010:35 | Address | &:r2010_11 |
|
||||
| ir.cpp:2010:9:2010:35 | Address | &:r2010_20 |
|
||||
| ir.cpp:2010:9:2010:35 | Load | m2010_4 |
|
||||
| ir.cpp:2010:9:2010:35 | Phi | from 11:m2010_12 |
|
||||
| ir.cpp:2010:9:2010:35 | Phi | from 12:m2010_21 |
|
||||
| ir.cpp:2010:9:2010:35 | StoreValue | r2010_6 |
|
||||
| ir.cpp:2010:13:2010:13 | Address | &:r2010_9 |
|
||||
| ir.cpp:2010:13:2010:13 | Load | m2006_8 |
|
||||
| ir.cpp:2010:13:2010:13 | StoreValue | r2010_10 |
|
||||
| ir.cpp:2010:17:2010:17 | Address | &:r2010_17 |
|
||||
| ir.cpp:2010:17:2010:35 | StoreValue | r2010_19 |
|
||||
| ir.cpp:2010:21:2010:35 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:21:2010:35 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:21:2010:35 | Load | m2010_15 |
|
||||
| ir.cpp:2010:21:2010:35 | StoreValue | r2010_14 |
|
||||
| ir.cpp:2010:21:2010:35 | StoreValue | r2010_16 |
|
||||
| ir.cpp:2010:21:2010:35 | Unary | r2010_16 |
|
||||
| ir.cpp:2010:6:2010:6 | Address | &:r2010_11 |
|
||||
| ir.cpp:2010:6:2010:6 | Unary | r2010_11 |
|
||||
| ir.cpp:2010:6:2010:18 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:10:2010:10 | Address | &:r2010_5 |
|
||||
| ir.cpp:2010:10:2010:10 | Condition | r2010_6 |
|
||||
| ir.cpp:2010:10:2010:10 | Load | m2006_6 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_9 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_17 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_21 |
|
||||
| ir.cpp:2010:10:2010:18 | Load | m2010_8 |
|
||||
| ir.cpp:2010:10:2010:18 | Phi | from 11:m2010_18 |
|
||||
| ir.cpp:2010:10:2010:18 | Phi | from 12:m2010_22 |
|
||||
| ir.cpp:2010:10:2010:18 | StoreValue | r2010_10 |
|
||||
| ir.cpp:2010:14:2010:14 | Address | &:r2010_15 |
|
||||
| ir.cpp:2010:14:2010:14 | Load | m2006_8 |
|
||||
| ir.cpp:2010:14:2010:14 | StoreValue | r2010_16 |
|
||||
| ir.cpp:2010:18:2010:18 | Address | &:r2010_19 |
|
||||
| ir.cpp:2010:18:2010:18 | Load | m2006_10 |
|
||||
| ir.cpp:2010:18:2010:18 | StoreValue | r2010_20 |
|
||||
| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:23:2010:37 | Load | m2010_3 |
|
||||
| ir.cpp:2010:23:2010:37 | StoreValue | r2010_2 |
|
||||
| ir.cpp:2010:23:2010:37 | StoreValue | r2010_4 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
@@ -9280,7 +9283,7 @@
|
||||
| ir.cpp:2014:13:2014:29 | SideEffect | m2014_8 |
|
||||
| ir.cpp:2017:6:2017:25 | ChiPartial | partial:m2017_3 |
|
||||
| ir.cpp:2017:6:2017:25 | ChiTotal | total:m2017_2 |
|
||||
| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_14 |
|
||||
| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_32 |
|
||||
| ir.cpp:2017:32:2017:32 | Address | &:r2017_5 |
|
||||
| ir.cpp:2017:52:2017:52 | Address | &:r2017_7 |
|
||||
| ir.cpp:2017:72:2017:72 | Address | &:r2017_9 |
|
||||
@@ -9423,60 +9426,58 @@
|
||||
| ir.cpp:2020:34:2020:51 | Load | m2020_40 |
|
||||
| ir.cpp:2020:34:2020:51 | SideEffect | ~m2019_16 |
|
||||
| ir.cpp:2020:34:2020:51 | StoreValue | r2020_41 |
|
||||
| ir.cpp:2021:5:2021:5 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:5:2021:5 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:5:2021:5 | Arg(this) | this:r2021_1 |
|
||||
| ir.cpp:2021:5:2021:5 | ChiPartial | partial:m2021_17 |
|
||||
| ir.cpp:2021:5:2021:5 | ChiTotal | total:m2020_20 |
|
||||
| ir.cpp:2021:5:2021:5 | SideEffect | m2020_20 |
|
||||
| ir.cpp:2021:7:2021:7 | CallTarget | func:r2021_2 |
|
||||
| ir.cpp:2021:7:2021:7 | ChiPartial | partial:m2021_13 |
|
||||
| ir.cpp:2021:7:2021:7 | ChiTotal | total:m2021_6 |
|
||||
| ir.cpp:2021:7:2021:7 | SideEffect | ~m2021_6 |
|
||||
| ir.cpp:2021:7:2021:7 | Unary | r2021_12 |
|
||||
| ir.cpp:2021:9:2021:9 | Address | &:r2021_3 |
|
||||
| ir.cpp:2021:9:2021:9 | Condition | r2021_4 |
|
||||
| ir.cpp:2021:9:2021:9 | Load | m2017_6 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_8 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_11 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_21 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_43 |
|
||||
| ir.cpp:2021:9:2021:38 | Arg(0) | 0:r2021_11 |
|
||||
| ir.cpp:2021:9:2021:38 | Load | m2021_7 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 11:m2021_22 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 11:~m2020_16 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 12:m2021_44 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 12:~m2021_37 |
|
||||
| ir.cpp:2021:9:2021:38 | SideEffect | ~m2021_14 |
|
||||
| ir.cpp:2021:9:2021:38 | Unary | r2021_9 |
|
||||
| ir.cpp:2021:9:2021:38 | Unary | r2021_10 |
|
||||
| ir.cpp:2021:13:2021:13 | StoreValue | r2021_20 |
|
||||
| ir.cpp:2021:17:2021:17 | Address | &:r2021_23 |
|
||||
| ir.cpp:2021:17:2021:17 | Address | &:r2021_23 |
|
||||
| ir.cpp:2021:17:2021:17 | Arg(this) | this:r2021_23 |
|
||||
| ir.cpp:2021:17:2021:17 | ChiPartial | partial:m2021_40 |
|
||||
| ir.cpp:2021:17:2021:17 | ChiTotal | total:m2017_10 |
|
||||
| ir.cpp:2021:17:2021:17 | SideEffect | m2017_10 |
|
||||
| ir.cpp:2021:19:2021:19 | CallTarget | func:r2021_24 |
|
||||
| ir.cpp:2021:19:2021:19 | ChiPartial | partial:m2021_36 |
|
||||
| ir.cpp:2021:19:2021:19 | ChiTotal | total:m2021_30 |
|
||||
| ir.cpp:2021:19:2021:19 | SideEffect | ~m2021_30 |
|
||||
| ir.cpp:2021:19:2021:19 | Unary | r2021_35 |
|
||||
| ir.cpp:2021:19:2021:39 | StoreValue | r2021_42 |
|
||||
| ir.cpp:2021:21:2021:38 | Address | &:r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | Address | &:r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | Address | &:r2021_34 |
|
||||
| ir.cpp:2021:21:2021:38 | Arg(0) | 0:r2021_34 |
|
||||
| ir.cpp:2021:21:2021:38 | Arg(this) | this:r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | CallTarget | func:r2021_27 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiPartial | partial:m2021_29 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiPartial | partial:m2021_31 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiTotal | total:m2020_16 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiTotal | total:m2021_26 |
|
||||
| ir.cpp:2021:21:2021:38 | SideEffect | ~m2020_16 |
|
||||
| ir.cpp:2021:21:2021:38 | SideEffect | ~m2021_32 |
|
||||
| ir.cpp:2021:21:2021:38 | Unary | r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | Unary | r2021_33 |
|
||||
| ir.cpp:2021:5:2021:19 | ChiPartial | partial:m2021_35 |
|
||||
| ir.cpp:2021:5:2021:19 | ChiTotal | total:m2021_17 |
|
||||
| ir.cpp:2021:5:2021:19 | SideEffect | m2021_17 |
|
||||
| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | Arg(this) | this:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | ChiPartial | partial:m2021_16 |
|
||||
| ir.cpp:2021:6:2021:6 | ChiTotal | total:m2020_20 |
|
||||
| ir.cpp:2021:6:2021:6 | SideEffect | m2020_20 |
|
||||
| ir.cpp:2021:8:2021:8 | CallTarget | func:r2021_2 |
|
||||
| ir.cpp:2021:8:2021:8 | ChiPartial | partial:m2021_12 |
|
||||
| ir.cpp:2021:8:2021:8 | ChiTotal | total:m2020_16 |
|
||||
| ir.cpp:2021:8:2021:8 | SideEffect | ~m2020_16 |
|
||||
| ir.cpp:2021:8:2021:8 | Unary | r2021_11 |
|
||||
| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 |
|
||||
| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 |
|
||||
| ir.cpp:2021:8:2021:19 | Arg(this) | this:r2021_18 |
|
||||
| ir.cpp:2021:10:2021:10 | Address | &:r2021_3 |
|
||||
| ir.cpp:2021:10:2021:10 | Condition | r2021_4 |
|
||||
| ir.cpp:2021:10:2021:10 | Load | m2017_6 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_7 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_10 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_39 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_42 |
|
||||
| ir.cpp:2021:10:2021:18 | Arg(0) | 0:r2021_10 |
|
||||
| ir.cpp:2021:10:2021:18 | Load | m2021_6 |
|
||||
| ir.cpp:2021:10:2021:18 | Phi | from 11:m2021_40 |
|
||||
| ir.cpp:2021:10:2021:18 | Phi | from 12:m2021_43 |
|
||||
| ir.cpp:2021:10:2021:18 | SideEffect | ~m2021_13 |
|
||||
| ir.cpp:2021:10:2021:18 | Unary | r2021_8 |
|
||||
| ir.cpp:2021:10:2021:18 | Unary | r2021_9 |
|
||||
| ir.cpp:2021:14:2021:14 | StoreValue | r2021_38 |
|
||||
| ir.cpp:2021:18:2021:18 | StoreValue | r2021_41 |
|
||||
| ir.cpp:2021:21:2021:21 | CallTarget | func:r2021_19 |
|
||||
| ir.cpp:2021:21:2021:21 | ChiPartial | partial:m2021_31 |
|
||||
| ir.cpp:2021:21:2021:21 | ChiTotal | total:m2021_25 |
|
||||
| ir.cpp:2021:21:2021:21 | SideEffect | ~m2021_25 |
|
||||
| ir.cpp:2021:21:2021:21 | Unary | r2021_30 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_29 |
|
||||
| ir.cpp:2021:23:2021:40 | Arg(0) | 0:r2021_29 |
|
||||
| ir.cpp:2021:23:2021:40 | Arg(this) | this:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | CallTarget | func:r2021_22 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_24 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_26 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_13 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_21 |
|
||||
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_13 |
|
||||
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_27 |
|
||||
| ir.cpp:2021:23:2021:40 | Unary | r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Unary | r2021_28 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -10529,9 +10529,10 @@ ir.cpp:
|
||||
# 1999| r1999_5(int) = Load[#temp1999:9] : &:r1999_4, ~m?
|
||||
# 1999| r1999_6(glval<int>) = VariableAddress[z] :
|
||||
# 1999| mu1999_7(int) = Store[z] : &:r1999_6, r1999_5
|
||||
# 2000| r2000_1(glval<bool>) = VariableAddress[a] :
|
||||
# 2000| r2000_2(bool) = Load[a] : &:r2000_1, ~m?
|
||||
# 2000| v2000_3(void) = ConditionalBranch : r2000_2
|
||||
# 2000| r2000_1(int) = Constant[7] :
|
||||
# 2000| r2000_2(glval<bool>) = VariableAddress[a] :
|
||||
# 2000| r2000_3(bool) = Load[a] : &:r2000_2, ~m?
|
||||
# 2000| v2000_4(void) = ConditionalBranch : r2000_3
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
@@ -10548,26 +10549,24 @@ ir.cpp:
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2000| Block 10
|
||||
# 2000| r2000_4(glval<unknown>) = VariableAddress[#temp2000:5] :
|
||||
# 2000| r2000_5(glval<int>) = Load[#temp2000:5] : &:r2000_4, ~m?
|
||||
# 2000| r2000_5(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| r2000_6(glval<int>) = Load[#temp2000:6] : &:r2000_5, ~m?
|
||||
# 2000| mu2000_7(int) = Store[?] : &:r2000_6, r2000_1
|
||||
# 2001| v2001_1(void) = NoOp :
|
||||
# 1996| v1996_12(void) = ReturnVoid :
|
||||
# 1996| v1996_13(void) = AliasedUse : ~m?
|
||||
# 1996| v1996_14(void) = ExitFunction :
|
||||
|
||||
# 2000| Block 11
|
||||
# 2000| r2000_6(glval<int>) = VariableAddress[x] :
|
||||
# 2000| r2000_7(glval<unknown>) = VariableAddress[#temp2000:5] :
|
||||
# 2000| mu2000_8(glval<int>) = Store[#temp2000:5] : &:r2000_7, r2000_6
|
||||
# 2000| r2000_8(glval<int>) = VariableAddress[x] :
|
||||
# 2000| r2000_9(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| mu2000_10(glval<int>) = Store[#temp2000:6] : &:r2000_9, r2000_8
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2000| Block 12
|
||||
# 2000| r2000_9(int) = Constant[7] :
|
||||
# 2000| r2000_10(glval<int>) = VariableAddress[y] :
|
||||
# 2000| mu2000_11(int) = Store[y] : &:r2000_10, r2000_9
|
||||
# 2000| r2000_12(glval<int>) = CopyValue : r2000_10
|
||||
# 2000| r2000_13(glval<unknown>) = VariableAddress[#temp2000:5] :
|
||||
# 2000| mu2000_14(glval<int>) = Store[#temp2000:5] : &:r2000_13, r2000_12
|
||||
# 2000| r2000_11(glval<int>) = VariableAddress[y] :
|
||||
# 2000| r2000_12(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| mu2000_13(glval<int>) = Store[#temp2000:6] : &:r2000_12, r2000_11
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2006| void TernaryTestPodObj(bool, TernaryPodObj, TernaryPodObj, TernaryPodObj)
|
||||
@@ -10649,15 +10648,19 @@ ir.cpp:
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 2009| Block 7
|
||||
# 2009| r2009_5(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m?
|
||||
# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6
|
||||
# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m?
|
||||
# 2009| r2009_9(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8
|
||||
# 2010| r2010_1(glval<bool>) = VariableAddress[a] :
|
||||
# 2010| r2010_2(bool) = Load[a] : &:r2010_1, ~m?
|
||||
# 2010| v2010_3(void) = ConditionalBranch : r2010_2
|
||||
# 2009| r2009_5(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m?
|
||||
# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6
|
||||
# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m?
|
||||
# 2009| r2009_9(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8
|
||||
# 2010| r2010_1(glval<TernaryPodObj>) = VariableAddress[#temp2010:23] :
|
||||
# 2010| r2010_2(TernaryPodObj) = Constant[0] :
|
||||
# 2010| mu2010_3(TernaryPodObj) = Store[#temp2010:23] : &:r2010_1, r2010_2
|
||||
# 2010| r2010_4(TernaryPodObj) = Load[#temp2010:23] : &:r2010_1, ~m?
|
||||
# 2010| r2010_5(glval<bool>) = VariableAddress[a] :
|
||||
# 2010| r2010_6(bool) = Load[a] : &:r2010_5, ~m?
|
||||
# 2010| v2010_7(void) = ConditionalBranch : r2010_6
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
@@ -10680,32 +10683,29 @@ ir.cpp:
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2010| Block 10
|
||||
# 2010| r2010_4(glval<TernaryPodObj>) = VariableAddress[#temp2010:9] :
|
||||
# 2010| r2010_5(TernaryPodObj) = Load[#temp2010:9] : &:r2010_4, ~m?
|
||||
# 2010| r2010_6(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2010| mu2010_7(TernaryPodObj) = Store[z] : &:r2010_6, r2010_5
|
||||
# 2011| v2011_1(void) = NoOp :
|
||||
# 2006| v2006_12(void) = ReturnVoid :
|
||||
# 2006| v2006_13(void) = AliasedUse : ~m?
|
||||
# 2006| v2006_14(void) = ExitFunction :
|
||||
# 2010| r2010_8(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| r2010_9(TernaryPodObj) = Load[#temp2010:10] : &:r2010_8, ~m?
|
||||
# 2010| r2010_10(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2010| mu2010_11(TernaryPodObj) = Store[z] : &:r2010_10, r2010_9
|
||||
# 2010| r2010_12(glval<TernaryPodObj>) = CopyValue : r2010_10
|
||||
# 2010| mu2010_13(TernaryPodObj) = Store[?] : &:r2010_12, r2010_4
|
||||
# 2011| v2011_1(void) = NoOp :
|
||||
# 2006| v2006_12(void) = ReturnVoid :
|
||||
# 2006| v2006_13(void) = AliasedUse : ~m?
|
||||
# 2006| v2006_14(void) = ExitFunction :
|
||||
|
||||
# 2010| Block 11
|
||||
# 2010| r2010_8(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2010| r2010_9(TernaryPodObj) = Load[x] : &:r2010_8, ~m?
|
||||
# 2010| r2010_10(glval<TernaryPodObj>) = VariableAddress[#temp2010:9] :
|
||||
# 2010| mu2010_11(TernaryPodObj) = Store[#temp2010:9] : &:r2010_10, r2010_9
|
||||
# 2010| r2010_14(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2010| r2010_15(TernaryPodObj) = Load[x] : &:r2010_14, ~m?
|
||||
# 2010| r2010_16(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| mu2010_17(TernaryPodObj) = Store[#temp2010:10] : &:r2010_16, r2010_15
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2010| Block 12
|
||||
# 2010| r2010_12(glval<TernaryPodObj>) = VariableAddress[#temp2010:21] :
|
||||
# 2010| r2010_13(TernaryPodObj) = Constant[0] :
|
||||
# 2010| mu2010_14(TernaryPodObj) = Store[#temp2010:21] : &:r2010_12, r2010_13
|
||||
# 2010| r2010_15(TernaryPodObj) = Load[#temp2010:21] : &:r2010_12, ~m?
|
||||
# 2010| r2010_16(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2010| mu2010_17(TernaryPodObj) = Store[y] : &:r2010_16, r2010_15
|
||||
# 2010| r2010_18(TernaryPodObj) = CopyValue : r2010_15
|
||||
# 2010| r2010_19(glval<TernaryPodObj>) = VariableAddress[#temp2010:9] :
|
||||
# 2010| mu2010_20(TernaryPodObj) = Store[#temp2010:9] : &:r2010_19, r2010_18
|
||||
# 2010| r2010_18(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2010| r2010_19(TernaryPodObj) = Load[y] : &:r2010_18, ~m?
|
||||
# 2010| r2010_20(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| mu2010_21(TernaryPodObj) = Store[#temp2010:10] : &:r2010_20, r2010_19
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2013| TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&)
|
||||
@@ -10931,46 +10931,46 @@ ir.cpp:
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2021| Block 10
|
||||
# 2021| r2021_6(glval<unknown>) = VariableAddress[#temp2021:9] :
|
||||
# 2021| r2021_7(glval<TernaryNonPodObj>) = Load[#temp2021:9] : &:r2021_6, ~m?
|
||||
# 2021| r2021_8(glval<TernaryNonPodObj>) = Convert : r2021_7
|
||||
# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8
|
||||
# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9
|
||||
# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m?
|
||||
# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m?
|
||||
# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1
|
||||
# 2021| r2021_15(glval<TernaryNonPodObj>) = CopyValue : r2021_10
|
||||
# 2022| v2022_1(void) = NoOp :
|
||||
# 2017| v2017_12(void) = ReturnVoid :
|
||||
# 2017| v2017_13(void) = AliasedUse : ~m?
|
||||
# 2017| v2017_14(void) = ExitFunction :
|
||||
# 2021| r2021_6(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| r2021_7(glval<TernaryNonPodObj>) = Load[#temp2021:10] : &:r2021_6, ~m?
|
||||
# 2021| r2021_8(glval<TernaryNonPodObj>) = Convert : r2021_7
|
||||
# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8
|
||||
# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9
|
||||
# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m?
|
||||
# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m?
|
||||
# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1
|
||||
# 2021| r2021_15(glval<TernaryNonPodObj>) = CopyValue : r2021_10
|
||||
# 2021| r2021_16(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2021| r2021_17(glval<TernaryNonPodObj>) = VariableAddress[#temp2021:23] :
|
||||
# 2021| mu2021_18(TernaryNonPodObj) = Uninitialized[#temp2021:23] : &:r2021_17
|
||||
# 2021| r2021_19(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2021| v2021_20(void) = Call[TernaryNonPodObj] : func:r2021_19, this:r2021_17
|
||||
# 2021| mu2021_21(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| mu2021_22(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_17
|
||||
# 2021| r2021_23(glval<TernaryNonPodObj>) = Convert : r2021_17
|
||||
# 2021| r2021_24(TernaryNonPodObj &) = CopyValue : r2021_23
|
||||
# 2021| r2021_25(TernaryNonPodObj &) = Call[operator=] : func:r2021_16, this:r2021_15, 0:r2021_24
|
||||
# 2021| mu2021_26(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_27(void) = ^IndirectReadSideEffect[-1] : &:r2021_15, ~m?
|
||||
# 2021| v2021_28(void) = ^BufferReadSideEffect[0] : &:r2021_24, ~m?
|
||||
# 2021| mu2021_29(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_15
|
||||
# 2021| r2021_30(glval<TernaryNonPodObj>) = CopyValue : r2021_25
|
||||
# 2022| v2022_1(void) = NoOp :
|
||||
# 2017| v2017_12(void) = ReturnVoid :
|
||||
# 2017| v2017_13(void) = AliasedUse : ~m?
|
||||
# 2017| v2017_14(void) = ExitFunction :
|
||||
|
||||
# 2021| Block 11
|
||||
# 2021| r2021_16(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2021| r2021_17(glval<unknown>) = VariableAddress[#temp2021:9] :
|
||||
# 2021| mu2021_18(glval<TernaryNonPodObj>) = Store[#temp2021:9] : &:r2021_17, r2021_16
|
||||
# 2021| r2021_31(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2021| r2021_32(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| mu2021_33(glval<TernaryNonPodObj>) = Store[#temp2021:10] : &:r2021_32, r2021_31
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2021| Block 12
|
||||
# 2021| r2021_19(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2021| r2021_20(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2021| r2021_21(glval<TernaryNonPodObj>) = VariableAddress[#temp2021:21] :
|
||||
# 2021| mu2021_22(TernaryNonPodObj) = Uninitialized[#temp2021:21] : &:r2021_21
|
||||
# 2021| r2021_23(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2021| v2021_24(void) = Call[TernaryNonPodObj] : func:r2021_23, this:r2021_21
|
||||
# 2021| mu2021_25(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| mu2021_26(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_21
|
||||
# 2021| r2021_27(glval<TernaryNonPodObj>) = Convert : r2021_21
|
||||
# 2021| r2021_28(TernaryNonPodObj &) = CopyValue : r2021_27
|
||||
# 2021| r2021_29(TernaryNonPodObj &) = Call[operator=] : func:r2021_20, this:r2021_19, 0:r2021_28
|
||||
# 2021| mu2021_30(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_31(void) = ^IndirectReadSideEffect[-1] : &:r2021_19, ~m?
|
||||
# 2021| v2021_32(void) = ^BufferReadSideEffect[0] : &:r2021_28, ~m?
|
||||
# 2021| mu2021_33(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_19
|
||||
# 2021| r2021_34(glval<TernaryNonPodObj>) = CopyValue : r2021_29
|
||||
# 2021| r2021_35(glval<unknown>) = VariableAddress[#temp2021:9] :
|
||||
# 2021| mu2021_36(glval<TernaryNonPodObj>) = Store[#temp2021:9] : &:r2021_35, r2021_34
|
||||
# 2021| r2021_34(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2021| r2021_35(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| mu2021_36(glval<TernaryNonPodObj>) = Store[#temp2021:10] : &:r2021_35, r2021_34
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
perf-regression.cpp:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
.. pull-quote:: Note
|
||||
|
||||
The data flow library described here is available from CodeQL 2.12.5 onwards. For information on the previous version of the library, see :ref:`Analyzing data flow in C and C++ <analyzing-data-flow-in-cpp>`.
|
||||
The data flow library described here is available from CodeQL 2.12.5 onwards. With the release of CodeQL 2.13.0 the library uses the new modular API for data flow. For information on the previous version of the library, see :ref:`Analyzing data flow in C and C++ <analyzing-data-flow-in-cpp>` and for information about the new modular API and how to migrate any existing queries to the updated data flow library, see `New dataflow API for CodeQL query writing <https://gh.io/codeql-new-dataflow-api>`__.
|
||||
|
||||
Analyzing data flow in C and C++ (new)
|
||||
======================================
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
.. pull-quote:: Note
|
||||
|
||||
The data flow library used in this article has been replaced with an improved library which is available from CodeQL 2.12.5 onwards, see :ref:`Analyzing data flow in C and C++ (new) <analyzing-data-flow-in-cpp-new>`. The old library has been deprecated in CodeQL 2.14.1 and will be removed in a later release.
|
||||
The data flow library used in this article has been replaced with an improved library which is available from CodeQL 2.12.5 onwards, see :ref:`Analyzing data flow in C and C++ (new) <analyzing-data-flow-in-cpp-new>`. The old library has been deprecated in CodeQL 2.14.1 and will be removed in a later release. With the release of CodeQL 2.13.0 both libraries use the new modular API for data flow.
|
||||
|
||||
Analyzing data flow in C and C++
|
||||
================================
|
||||
|
||||
@@ -12,6 +12,8 @@ This article describes how data flow analysis is implemented in the CodeQL libra
|
||||
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
|
||||
For a more general introduction to modeling data flow, see ":ref:`About data flow analysis <about-data-flow-analysis>`."
|
||||
|
||||
.. include:: ../reusables/new-data-flow-api.rst
|
||||
|
||||
Local data flow
|
||||
---------------
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ The following sections describe how to use the libraries for local data flow, gl
|
||||
|
||||
For a more general introduction to modeling data flow, see ":ref:`About data flow analysis <about-data-flow-analysis>`."
|
||||
|
||||
.. include:: ../reusables/new-data-flow-api.rst
|
||||
|
||||
Local data flow
|
||||
---------------
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ This article describes how data flow analysis is implemented in the CodeQL libra
|
||||
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
|
||||
For a more general introduction to modeling data flow, see ":ref:`About data flow analysis <about-data-flow-analysis>`."
|
||||
|
||||
.. include:: ../reusables/new-data-flow-api.rst
|
||||
|
||||
Local data flow
|
||||
---------------
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ This article describes how data flow analysis is implemented in the CodeQL libra
|
||||
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
|
||||
For a more general introduction to modeling data flow, see ":ref:`About data flow analysis <about-data-flow-analysis>`."
|
||||
|
||||
.. include:: ../reusables/new-data-flow-api.rst
|
||||
|
||||
Local data flow
|
||||
---------------
|
||||
|
||||
|
||||
4
docs/codeql/reusables/new-data-flow-api.rst
Normal file
4
docs/codeql/reusables/new-data-flow-api.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
.. pull-quote:: Note
|
||||
|
||||
The new modular API for data flow described here is available alongside the previous library from CodeQL 2.13.0 onwards. For information about how the library has changed and how to migrate any existing queries to the modular API, see `New dataflow API for CodeQL query writing <https://gh.io/codeql-new-dataflow-api>`__.
|
||||
|
||||
@@ -5,6 +5,8 @@ Creating path queries
|
||||
|
||||
You can create path queries to visualize the flow of information through a codebase.
|
||||
|
||||
.. include:: ../reusables/new-data-flow-api.rst
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
Debugging data-flow queries using partial flow
|
||||
==============================================
|
||||
|
||||
.. include:: ../reusables/new-data-flow-api.rst
|
||||
|
||||
If a data-flow query doesn't produce the results you expect to see, you can use partial flow to debug the problem.
|
||||
|
||||
In CodeQL, you can use :ref:`data flow analysis <about-data-flow-analysis>` to compute the possible values that a variable can hold at various points in a program.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added more dataflow steps for `java.io.InputStream`s that wrap other `java.io.InputStream`s.
|
||||
@@ -4849,15 +4849,6 @@ extensions:
|
||||
- ["org.apache.struts2", "StrutsException", true, "StrutsException", "(Throwable,Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.apache.struts2", "StrutsException", true, "StrutsException", "(Throwable,Object)", "", "Argument[1]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.apache.struts2", "StrutsException", true, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "Order", "(String,String,int)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "Order", "(String,String,int)", "", "Argument[1]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "getClientName", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "getId", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "setClientName", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "setId", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", true, "create", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", true, "setId", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: neutralModel
|
||||
@@ -6886,19 +6877,5 @@ extensions:
|
||||
- ["org.apache.struts2", "ServletActionContext", "setResponse", "(HttpServletResponse)", "summary", "df-generated"]
|
||||
- ["org.apache.struts2", "ServletActionContext", "setServletContext", "(ServletContext)", "summary", "df-generated"]
|
||||
- ["org.apache.struts2", "ServletCache", "clear", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "IndexController", "index", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", "getAmount", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", "setAmount", "(int)", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "deleteConfirm", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "destroy", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "edit", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "editNew", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "index", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "show", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "update", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "get", "(String)", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "getAll", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "remove", "(String)", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "save", "(Order)", "summary", "df-generated"]
|
||||
- ["org.w3c.dom", "Document", "getElementsByTagName", "(String)", "summary", "df-generated"]
|
||||
- ["org.w3c.dom", "Document", "getElementsByTagNameNS", "(String,String)", "summary", "df-generated"]
|
||||
|
||||
@@ -177,6 +177,11 @@ class TypeObjectInputStream extends RefType {
|
||||
TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") }
|
||||
}
|
||||
|
||||
/** The class `java.io.InputStream`. */
|
||||
class TypeInputStream extends RefType {
|
||||
TypeInputStream() { this.hasQualifiedName("java.io", "InputStream") }
|
||||
}
|
||||
|
||||
/** The class `java.nio.file.Paths`. */
|
||||
class TypePaths extends Class {
|
||||
TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") }
|
||||
|
||||
@@ -20,11 +20,11 @@ private module Frameworks {
|
||||
private import semmle.code.java.frameworks.Guice
|
||||
private import semmle.code.java.frameworks.IoJsonWebToken
|
||||
private import semmle.code.java.frameworks.jackson.JacksonSerializability
|
||||
private import semmle.code.java.frameworks.InputStream
|
||||
private import semmle.code.java.frameworks.Properties
|
||||
private import semmle.code.java.frameworks.Protobuf
|
||||
private import semmle.code.java.frameworks.ratpack.RatpackExec
|
||||
private import semmle.code.java.frameworks.stapler.Stapler
|
||||
private import semmle.code.java.JDK
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -757,7 +757,7 @@ private predicate baseBound(Expr e, int b, boolean upper) {
|
||||
or
|
||||
exists(Method read |
|
||||
e.(MethodAccess).getMethod().overrides*(read) and
|
||||
read.getDeclaringType().hasQualifiedName("java.io", "InputStream") and
|
||||
read.getDeclaringType() instanceof TypeInputStream and
|
||||
read.hasName("read") and
|
||||
read.getNumberOfParameters() = 0
|
||||
|
|
||||
|
||||
@@ -239,7 +239,7 @@ private class BulkData extends RefType {
|
||||
this.(Array).getElementType().(PrimitiveType).hasName(["byte", "char"])
|
||||
or
|
||||
exists(RefType t | this.getASourceSupertype*() = t |
|
||||
t.hasQualifiedName("java.io", "InputStream") or
|
||||
t instanceof TypeInputStream or
|
||||
t.hasQualifiedName("java.nio", "ByteBuffer") or
|
||||
t.hasQualifiedName("java.lang", "Readable") or
|
||||
t.hasQualifiedName("java.io", "DataInput") or
|
||||
@@ -259,7 +259,7 @@ private class BulkData extends RefType {
|
||||
private predicate inputStreamWrapper(Constructor c, int argi) {
|
||||
not c.fromSource() and
|
||||
c.getParameterType(argi) instanceof BulkData and
|
||||
c.getDeclaringType().getASourceSupertype+().hasQualifiedName("java.io", "InputStream")
|
||||
c.getDeclaringType().getASourceSupertype+() instanceof TypeInputStream
|
||||
}
|
||||
|
||||
/** An object construction that preserves the data flow status of any of its arguments. */
|
||||
|
||||
@@ -102,7 +102,7 @@ private module Dispatch {
|
||||
or
|
||||
t instanceof Interface and not t.fromSource()
|
||||
or
|
||||
t.hasQualifiedName("java.io", "InputStream")
|
||||
t instanceof TypeInputStream
|
||||
or
|
||||
t.hasQualifiedName("java.io", "Serializable")
|
||||
or
|
||||
|
||||
90
java/ql/lib/semmle/code/java/frameworks/InputStream.qll
Normal file
90
java/ql/lib/semmle/code/java/frameworks/InputStream.qll
Normal file
@@ -0,0 +1,90 @@
|
||||
/** Provides definitions related to `java.io.InputStream`. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
private import semmle.code.java.dataflow.SSA
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* A jump taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method
|
||||
* to a class instance expression of the type extending `InputStream`.
|
||||
*
|
||||
* This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will
|
||||
* normally only happen in nested classes.
|
||||
*/
|
||||
private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(InputStreamRead m, NestedClass wrapper |
|
||||
m.getDeclaringType() = wrapper and
|
||||
wrapper.getASourceSupertype+() instanceof TypeInputStream
|
||||
|
|
||||
n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and
|
||||
n2.asExpr()
|
||||
.(ClassInstanceExpr)
|
||||
.getConstructedType()
|
||||
.getASourceSupertype*()
|
||||
.getSourceDeclaration() = wrapper
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A local taint step from the definition of a captured variable, the capturer of which
|
||||
* updates the `bytes[]` parameter in an override of the `InputStream.read` method,
|
||||
* to a class instance expression of the type extending `InputStream`.
|
||||
*
|
||||
* This models how a subtype of `InputStream` could be tainted by capturing tainted variables in
|
||||
* the definition of its methods.
|
||||
*/
|
||||
private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer |
|
||||
wrapper.getASourceSupertype+() instanceof TypeInputStream and
|
||||
m.getDeclaringType() = wrapper and
|
||||
capturer.captures(captured) and
|
||||
TaintTracking::localTaint(DataFlow::exprNode(capturer.getAFirstUse()),
|
||||
any(DataFlow::PostUpdateNode pun |
|
||||
pun.getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess()
|
||||
)) and
|
||||
n2.asExpr()
|
||||
.(ClassInstanceExpr)
|
||||
.getConstructedType()
|
||||
.getASourceSupertype*()
|
||||
.getSourceDeclaration() = wrapper
|
||||
|
|
||||
n1.asExpr() = captured.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource()
|
||||
or
|
||||
captured.(SsaImplicitInit).isParameterDefinition(n1.asParameter())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype
|
||||
* to the call of the constructor, only if the argument is assigned to a class field.
|
||||
*
|
||||
* This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream,
|
||||
* and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations.
|
||||
*/
|
||||
private class InputStreamWrapperConstructorStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos |
|
||||
cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and
|
||||
cc.getArgument(pragma[only_bind_into](pos)) = a and
|
||||
cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and
|
||||
ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof
|
||||
TypeInputStream
|
||||
|
|
||||
n1.asExpr() = a and
|
||||
n2.asExpr() = cc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class InputStreamRead extends Method {
|
||||
InputStreamRead() {
|
||||
this.hasName("read") and
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeInputStream
|
||||
}
|
||||
}
|
||||
@@ -317,7 +317,7 @@ class SystemSetInputStreamMethod extends Method {
|
||||
SystemSetInputStreamMethod() {
|
||||
this.hasName("setIn") and
|
||||
this.getNumberOfParameters() = 1 and
|
||||
this.getParameter(0).getType().(RefType).hasQualifiedName("java.io", "InputStream") and
|
||||
this.getParameter(0).getType() instanceof TypeInputStream and
|
||||
this.getDeclaringType()
|
||||
.getAnAncestor()
|
||||
.getSourceDeclaration()
|
||||
|
||||
@@ -237,7 +237,7 @@ class SpringRequestMappingParameter extends Parameter {
|
||||
|
||||
private predicate isExplicitlyTaintedInput() {
|
||||
// InputStream or Reader parameters allow access to the body of a request
|
||||
this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "InputStream") or
|
||||
this.getType().(RefType).getAnAncestor() instanceof TypeInputStream or
|
||||
this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Reader") or
|
||||
// The SpringServletInputAnnotations allow access to the URI, request parameters, cookie values and the body of the request
|
||||
this.getAnAnnotation() instanceof SpringServletInputAnnotation or
|
||||
|
||||
139
java/ql/test/library-tests/dataflow/stream-read/A.java
Normal file
139
java/ql/test/library-tests/dataflow/stream-read/A.java
Normal file
@@ -0,0 +1,139 @@
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class A {
|
||||
|
||||
private static InputStream source() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void sink(Object s) {}
|
||||
|
||||
static class MyStream extends InputStream {
|
||||
private InputStream wrapped;
|
||||
|
||||
MyStream(InputStream wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return wrapped.read(b);
|
||||
}
|
||||
}
|
||||
|
||||
public static void testSeveralWrappers() {
|
||||
InputStream src = source();
|
||||
InputStream wrapper1 = new MyStream(src);
|
||||
sink(wrapper1); // $ hasTaintFlow
|
||||
InputStream wrapper2 = new MyStream(wrapper1);
|
||||
sink(wrapper2); // $ hasTaintFlow
|
||||
InputStream wrapper3 = new MyStream(wrapper2);
|
||||
sink(wrapper3); // $ hasTaintFlow
|
||||
|
||||
InputStream wrapper4 = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return wrapper3.read(b);
|
||||
|
||||
}
|
||||
};
|
||||
sink(wrapper4); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testAnonymous() throws Exception {
|
||||
InputStream wrapper = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
InputStream in = source();
|
||||
return in.read(b);
|
||||
}
|
||||
};
|
||||
sink(wrapper); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testAnonymousVarCapture() throws Exception {
|
||||
InputStream in = source();
|
||||
InputStream wrapper = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return in.read(b);
|
||||
|
||||
}
|
||||
};
|
||||
sink(wrapper); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static InputStream wrapStream(InputStream in) {
|
||||
return new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return in.read(b);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void testWrapCall() {
|
||||
sink(wrapStream(null)); // $ SPURIOUS: hasTaintFlow
|
||||
sink(wrapStream(source())); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testLocal() {
|
||||
|
||||
class LocalInputStream extends InputStream {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
InputStream in = source();
|
||||
return in.read(b);
|
||||
}
|
||||
}
|
||||
sink(new LocalInputStream()); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testLocalVarCapture() {
|
||||
InputStream in = source();
|
||||
|
||||
class LocalInputStream extends InputStream {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return in.read(b);
|
||||
}
|
||||
}
|
||||
sink(new LocalInputStream()); // $ hasTaintFlow
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
2
java/ql/test/library-tests/dataflow/stream-read/test.ql
Normal file
2
java/ql/test/library-tests/dataflow/stream-read/test.ql
Normal file
@@ -0,0 +1,2 @@
|
||||
import TestUtilities.InlineFlowTest
|
||||
import DefaultFlowTest
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
|
||||
* Added taint flow for `NSUserActivity.referrerURL`.
|
||||
@@ -83,7 +83,7 @@ private class UserActivityUrlInheritTaint extends TaintInheritingContent,
|
||||
{
|
||||
UserActivityUrlInheritTaint() {
|
||||
this.getField().getEnclosingDecl().asNominalTypeDecl().getName() = "NSUserActivity" and
|
||||
this.getField().getName() = "webpageURL"
|
||||
this.getField().getName() = ["webpageURL", "referrerURL"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about system
|
||||
* commands built from user-controlled sources (that is, command injection
|
||||
* vulnerabilities).
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A dataflow sink for command injection vulnerabilities.
|
||||
*/
|
||||
abstract class CommandInjectionSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A barrier for command injection vulnerabilities.
|
||||
*/
|
||||
abstract class CommandInjectionBarrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A unit class for adding additional flow steps.
|
||||
*/
|
||||
class CommandInjectionAdditionalFlowStep extends Unit {
|
||||
/**
|
||||
* Holds if the step from `node1` to `node2` should be considered a flow
|
||||
* step for paths related to command injection vulnerabilities.
|
||||
*/
|
||||
abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo);
|
||||
}
|
||||
|
||||
private class ProcessSink2 extends CommandInjectionSink instanceof DataFlow::Node {
|
||||
ProcessSink2() {
|
||||
exists(AssignExpr assign, ProcessHost s |
|
||||
assign.getDest() = s and
|
||||
this.asExpr() = assign.getSource()
|
||||
)
|
||||
or
|
||||
exists(AssignExpr assign, ProcessHost s, ArrayExpr a |
|
||||
assign.getDest() = s and
|
||||
a = assign.getSource() and
|
||||
this.asExpr() = a.getAnElement()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ProcessHost extends MemberRefExpr {
|
||||
ProcessHost() { this.getBase() instanceof ProcessRef }
|
||||
}
|
||||
|
||||
/** An expression of type `Process`. */
|
||||
private class ProcessRef extends Expr {
|
||||
ProcessRef() {
|
||||
this.getType() instanceof ProcessType or
|
||||
this.getType() = any(OptionalType t | t.getBaseType() instanceof ProcessType)
|
||||
}
|
||||
}
|
||||
|
||||
/** The type `Process`. */
|
||||
private class ProcessType extends NominalType {
|
||||
ProcessType() { this.getFullName() = "Process" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `DataFlow::Node` that is written into a `Process` object.
|
||||
*/
|
||||
private class ProcessSink extends CommandInjectionSink instanceof DataFlow::Node {
|
||||
ProcessSink() {
|
||||
// any write into a class derived from `Process` is a sink. For
|
||||
// example in `Process.launchPath = sensitive` the post-update node corresponding
|
||||
// with `Process.launchPath` is a sink.
|
||||
exists(NominalType t, Expr e |
|
||||
t.getABaseType*().getUnderlyingType().getName() = "Process" and
|
||||
e.getFullyConverted() = this.asExpr() and
|
||||
e.getFullyConverted().getType() = t
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink defined in a CSV model.
|
||||
*/
|
||||
private class DefaultCommandInjectionSink extends CommandInjectionSink {
|
||||
DefaultCommandInjectionSink() { sinkNode(this, "command-injection") }
|
||||
}
|
||||
31
swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll
Normal file
31
swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for reasoning about system
|
||||
* commands built from user-controlled sources (that is, Command injection
|
||||
* vulnerabilities).
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSources
|
||||
import codeql.swift.security.CommandInjectionExtensions
|
||||
|
||||
/**
|
||||
* A taint configuration for tainted data that reaches a Command Injection sink.
|
||||
*/
|
||||
module CommandInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof CommandInjectionSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof CommandInjectionBarrier }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
any(CommandInjectionAdditionalFlowStep s).step(nodeFrom, nodeTo)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect taint flow of tainted data that reaches a Command Injection sink.
|
||||
*/
|
||||
module CommandInjectionFlow = TaintTracking::Global<CommandInjectionConfig>;
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added new query "Command injection" (`swift/command-line-injection`). The query finds places where user input is used to execute system commands without proper escaping.
|
||||
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Constructing a system command with unsanitized user input is dangerous,
|
||||
since a malicious user may be able to craft input that executes arbitrary code.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
If possible, use hard-coded string literals to specify the command to run. Instead of interpreting
|
||||
user input directly as command names, examine the input and then choose among hard-coded string
|
||||
literals.
|
||||
</p>
|
||||
<p>
|
||||
If this is not possible, then add sanitization code to verify that the user input is safe before
|
||||
using it.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following examples execute code from user input without
|
||||
sanitizing it first:
|
||||
</p>
|
||||
<sample src="CommandInjectionBad.swift" />
|
||||
<p>
|
||||
If user input is used to construct a command it should be checked
|
||||
first. This ensures that the user cannot insert characters that have special
|
||||
meanings.
|
||||
</p>
|
||||
<sample src="CommandInjectionGood.swift" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name System command built from user-controlled sources
|
||||
* @description Building a system command from user-controlled sources is vulnerable to insertion of malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id swift/command-line-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.security.CommandInjectionQuery
|
||||
import CommandInjectionFlow::PathGraph
|
||||
|
||||
from CommandInjectionFlow::PathNode sourceNode, CommandInjectionFlow::PathNode sinkNode
|
||||
where CommandInjectionFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode, "This command depends on a $@.",
|
||||
sourceNode.getNode(), "user-provided value"
|
||||
@@ -0,0 +1,5 @@
|
||||
var task = Process()
|
||||
task.launchPath = "/bin/bash"
|
||||
task.arguments = ["-c", userControlledString] // BAD
|
||||
|
||||
task.launch()
|
||||
@@ -0,0 +1,13 @@
|
||||
func validateCommand(_ command: String) -> String? {
|
||||
let allowedCommands = ["ls -l", "pwd", "echo"]
|
||||
if allowedCommands.contains(command) {
|
||||
return command
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var task = Process()
|
||||
task.launchPath = "/bin/bash"
|
||||
task.arguments = ["-c", validateCommand(userControlledString)] // GOOD
|
||||
|
||||
task.launch()
|
||||
@@ -0,0 +1,3 @@
|
||||
deadEnd
|
||||
| customurlschemes.swift:94:59:94:76 | options |
|
||||
| customurlschemes.swift:133:59:133:76 | options |
|
||||
@@ -1,6 +1,21 @@
|
||||
import swift
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import FlowConfig
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
|
||||
module TestConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(CallExpr sinkCall |
|
||||
sinkCall.getStaticTarget().getName().matches("sink%") and
|
||||
sinkCall.getAnArgument().getExpr() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module TestFlow = TaintTracking::Global<TestConfiguration>;
|
||||
|
||||
string describe(FlowSource source) {
|
||||
source instanceof RemoteFlowSource and result = "remote"
|
||||
@@ -9,7 +24,7 @@ string describe(FlowSource source) {
|
||||
}
|
||||
|
||||
module FlowSourcesTest implements TestSig {
|
||||
string getARelevantTag() { result = "source" }
|
||||
string getARelevantTag() { result = ["source", "tainted"] }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(FlowSource source |
|
||||
@@ -19,6 +34,16 @@ module FlowSourcesTest implements TestSig {
|
||||
tag = "source" and
|
||||
value = describe(source)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node sink |
|
||||
// this is not really what the "flowsources" test is about, but sometimes it's helpful to
|
||||
// have sinks and confirm that taint reaches obvious points in the flow source test code.
|
||||
TestFlow::flowTo(sink) and
|
||||
location = sink.getLocation() and
|
||||
element = sink.toString() and
|
||||
tag = "tainted" and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,24 @@ protocol UIApplicationDelegate {
|
||||
}
|
||||
|
||||
class UIScene {
|
||||
class ConnectionOptions {}
|
||||
class ConnectionOptions {
|
||||
var userActivities: Set<NSUserActivity> { get { return Set() } }
|
||||
var urlContexts: Set<UIOpenURLContext> { get { return Set() } }
|
||||
}
|
||||
}
|
||||
|
||||
class UISceneSession {}
|
||||
|
||||
class NSUserActivity {}
|
||||
class NSUserActivity: Hashable {
|
||||
static func == (lhs: NSUserActivity, rhs: NSUserActivity) -> Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {}
|
||||
|
||||
var webpageURL: URL? { get { return nil } set { } }
|
||||
var referrerURL: URL? { get { return nil } set { } }
|
||||
}
|
||||
|
||||
class UIOpenURLContext: Hashable {
|
||||
static func == (lhs: UIOpenURLContext, rhs: UIOpenURLContext) -> Bool {
|
||||
@@ -39,6 +51,8 @@ class UIOpenURLContext: Hashable {
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {}
|
||||
|
||||
var url: URL { get { return URL() } }
|
||||
}
|
||||
|
||||
protocol UISceneDelegate {
|
||||
@@ -48,6 +62,8 @@ protocol UISceneDelegate {
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>)
|
||||
}
|
||||
|
||||
func sink(arg: Any) {}
|
||||
|
||||
// --- tests ---
|
||||
|
||||
class AppDelegate: UIApplicationDelegate {
|
||||
@@ -64,28 +80,88 @@ class AppDelegate: UIApplicationDelegate {
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
|
||||
launchOptions?[.url] // $ source=remote
|
||||
_ = launchOptions?[.url] // $ source=remote
|
||||
return true
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
|
||||
launchOptions?[.url] // $ source=remote
|
||||
_ = launchOptions?[.url] // $ source=remote
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class SceneDelegate : UISceneDelegate {
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote
|
||||
func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) {} // $ source=remote
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote
|
||||
for userActivity in options.userActivities {
|
||||
let x = userActivity.webpageURL
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
let y = userActivity.referrerURL
|
||||
sink(arg: y) // $ MISSING: tainted
|
||||
}
|
||||
|
||||
for urlContext in options.urlContexts {
|
||||
let z = urlContext.url
|
||||
sink(arg: z) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
|
||||
func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote
|
||||
let x = `continue`.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = `continue`.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote
|
||||
let x = didUpdate.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = didUpdate.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) { // $ source=remote
|
||||
for openURLContext in openURLContexts {
|
||||
let x = openURLContext.url
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Extended {}
|
||||
|
||||
extension Extended : UISceneDelegate {
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote
|
||||
func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) {} // $ source=remote
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote
|
||||
for userActivity in options.userActivities {
|
||||
let x = userActivity.webpageURL
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
let y = userActivity.referrerURL
|
||||
sink(arg: y) // $ MISSING: tainted
|
||||
}
|
||||
|
||||
for urlContext in options.urlContexts {
|
||||
let z = urlContext.url
|
||||
sink(arg: z) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
|
||||
func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote
|
||||
let x = `continue`.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = `continue`.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote
|
||||
let x = didUpdate.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = didUpdate.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) { // $ source=remote
|
||||
for openURLContext in openURLContexts {
|
||||
let x = openURLContext.url
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user